2009-06-02 3 views
12

Ich rannte in eine Situation, die anders scheint. Wenn ich im folgenden Codefragment die Zeile self.navigationController = nav entferne, wird die Ansicht des Root-Controllers nicht angezeigt, was darauf hindeutet, dass addSubview die Ansicht möglicherweise nicht wirklich behält, wie es sonst vorgeschlagen wird. Irgendeine Idee?Behält UIViews addSubview wirklich die Ansicht?

- (void)applicationDidFinishLaunching:(UIApplication *)application { 
    self.testViewController = [[TestViewController alloc] initWithNibName:@"TestView" bundle: [NSBundle mainBundle]]; 

    UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:self.testViewController]; 

    self.navigationController = nav; //<-- if this line is removed, test view won't show up 

    [window addSubview:nav.view]; 

    [nav release]; 
} 
+0

Ihre markierte Antwort ist nicht korrekt, aus Gründen, die ich unten kommentiert habe. –

Antwort

24

Diese Zeile:

[window addSubview:nav.view]; 

NICHT einen Blick auf den Bildschirm sofort hinzuzufügen. Es wird vom Betriebssystem in einer zukünftigen Laufschleife auf einem möglicherweise anderen Thread angezeigt. Die tatsächliche Implementierung können wir nicht sicher sein.

Aus diesem Grund definiert Apple Delegate-Methoden wie viewDidAppear/viewWillAppear, sonst würden wir sie nicht benötigen, da wir genau wissen würden, wann diese Ereignisse auftreten.

Außerdem fügt das Hinzufügen einer Unteransicht, wie Sie gesagt haben, in der Tat die Ansicht. Es tut NICHT aber behalten Sie die Ansicht Controller oder der Navigation Controller. Da der Navigationscontroller WILLS alle hinzugefügten View-Controller behält, müssen wir sie nicht mit einem ivar-Befehl zurückhalten.

Aber Ihr Verweis auf den Navigationscontroller muss bestehen über den Rahmen der Methode hinaus. oder abhängig von Ihrem Code könnte es freigegeben werden oder seine Referenz verloren haben.

So können Sie einen Verweis auf die Navigationssteuerung mit einem Ivar halten müssen und es wie so gesetzt:

self.navigationController = nav; 

Also auch wenn nav.view einen Zeiger auf testViewController.view enthält, hat die Anwendung keinen Hinweis des Navigationscontroller und, als Erweiterung, die Ansicht. Das Ergebnis ist ein leerer Bildschirm.


Um dies deutlicher zu machen, dass es nicht behalten/release Problem ist, Sie sind in der folgenden Methode tatsächlich undicht:

self.testViewController = [[TestViewController alloc] initWithNibName:@"TestView" bundle: [NSBundle mainBundle]]; 

Sie müssen Ihre Autorelease behalten/releases auszubalancieren von: So

self.testViewController = [[[TestViewController alloc] initWithNibName:@"TestView" bundle: [NSBundle mainBundle]] autorelease]; 

, das bedeutet, dass Ihre Sicht hat nie, nie jederzeit aufgehoben worden Sie diesen Code ran. Was uns weiter versichert, dass Ihr Thema in der Tat eine verlorene Referenz ist.

+0

Nette Arbeit Corey, wirklich wie die Erklärung, die Sie auslegten. – Boon

+1

Es ist falsch, dass _view_ aufgehoben wird, bevor das Fenster es behält. Wenn dies der Fall wäre, würden Sie eine Ausnahme sehen, wenn das Fenster versucht, auf das freizugebende Objekt zuzugreifen. Was freigegeben wird, ist der Nav-Controller, der verhindert, dass er seine Ansicht mit interessanten Inhalten (wie der Navigationsleiste und der Root-Ansicht) füllt. –

+0

Nachdem ich darüber nachgedacht habe, habe ich einige zusätzliche Informationen hinzugefügt, die auch erklären, was Sie sehen. –

0

Das sieht nicht wie eine Retain/Release-Frage für mich aus. Ihre Ansicht wird nicht angezeigt, wenn Sie self.navigationController = nav; auskommentieren, da dann in der nächsten Zeile [window addSubview:self.navigationController.view] Ihre Eigenschaft self.navigationController nicht festgelegt wird. Es ist wahrscheinlich Null oder es würde abstürzen, aber kann nicht ohne mehr Code sicher sagen.

+0

Ich habe den Code wieder auf den ursprünglichen Code aktualisiert, wenn die Dinge nicht funktionierten und ich Self.navigationController in Dinge einführen musste, um einen Verweis auf Nav zu halten. Auch, was Sie oben sehen, ist der ganze Code, den es gibt und nichts anderes. – Boon

+0

In Ziel-c beginnen die Ivars mit dem Wert 0. Also wäre self.navigationController einfach null. –

2

Das Problem ist wahrscheinlich nicht, dass die Ansicht nicht beibehalten wird, es ist, dass der Controller nicht beibehalten wird.

Ohne diese Zeile:

self.navigationController = nav 

Nichts die Navigationssteuerung wird beibehalten. Es wäre seltsam, wenn der View den Controller überlebt.

+0

Eine Ansicht ist nicht "magisch" an einen View-Controller gebunden. Eine Ansicht stirbt nicht einfach, weil ihr View-Controller stirbt. Wenn die Ansicht an anderer Stelle beibehalten wurde, überlebt sie alle View-Controller absolut. –

+0

Ich habe nicht gesagt, dass es nicht passieren würde. Ich sagte, es wäre seltsam, wenn man den anderen überlebt. Vor allem, wenn die Ansicht die Ansicht des Navigationscontrollers ist, was eine interne Ansichtshierarchie ist, die durch den Navigationscontroller eingeplant ist. –

+0

Wenn Sie der Konvention folgen, haben Sie Recht. Mein einziger Punkt ist, dass es kein Grund an und für sich ist. Der einzige Grund dafür ist, dass Sie normalerweise keinen View-Controller freigeben, bevor Sie seine Ansicht aus der View-Hierarchie entfernen. Es gibt jedoch keine Mechanismen in UIViewController, die Sie davon abhalten, dies zu tun, sondern nur aus der Praxis des richtigen Speichermanagements. –

Verwandte Themen