2012-03-28 2 views
7

Rein zufällig entdeckte ich, dass Aufruf [bar.view addSubview:[foo view]] nicht funktioniert, aber [bar.view addSubview:foo.view] tut im folgenden Code.Warum verhält sich [foo view] anders als foo.view in meinem Code?

foo=[fooViewController alloc] initWithNibName:@"fooViewController" andBundle:nil]; 
[self.view addSubview:foo.view];//here's where I swap the two commands out 
[foo aFunctionThatSendsAMessageToOneOfFoosSubViews]; 

(Das letzte Zeile ist, weil foo einige Unter Ansichten hat, die müssen vor eingerichtet werden zu laufen -. Vor allem ein UIWebView Wenn sie, bevor die Nachricht nicht die Nachricht gesendet instanziiert worden ist, gehen nil aufwickelt Mit foo)

ich dachte, diese beiden funktional identisch waren - dass foo.view die gleiche Getter aufruft, die [foo view] tut, aber in der Praxis nicht der Fall ist..; Die Punktsyntax erhält die gewünschten Ergebnisse, während die Verwendung der Klammern die Nachricht an nil sendet.

Wenn Sie mich vor zehn Minuten gefragt hätten, hätte ich Ihnen gesagt, der Unterschied zwischen den beiden Ausdrücken sei "Syntax und nichts anderes". Da ich eindeutig falsch liege, muss ich verstehen, WIE ich falsch liege, oder ich werde wieder darüber stolpern.

+0

Haben Sie versucht, die tatsächliche Ausgabe von '[foo view]' und 'foo.view' zu vergleichen? Sie müssen gleich sein. – Costique

+0

Eigentlich ja. Ich habe NSLog (@ "View Info:% @", [foo view]) und eine ähnliche foo.view-Anweisung verwendet. Identisch - auch wenn ich sie umkehre. Die scheinen das exakt gleiche Ding zurückzugeben. – RonLugge

+1

Wenn Sie Ihren Code im Assistenten-Editor von Xcode anzeigen und im Drop-down-Menü "Tuxedo" die Option "Assembly" auswählen, bemerken Sie einen Unterschied zwischen der Verwendung der Punktsyntax und Klammern? –

Antwort

3

Sie sind funktionell gleichwertig. Ich denke, das ist eine Wettlaufbedingung. Wenn Sie in diesem Code zuerst foo.view aufrufen, ist die Ansicht noch nicht geladen, und ein Anruf wird an [foo loadView] gesendet. Sie können nicht sicher sein, dass die Ansicht geladen ist, bis [foo viewDidLoad] oder foo.isViewLoaded == YES aufgerufen wird.

Sie müssen sicherstellen, dass die Ansicht geladen ist, bevor Sie Aktionen ausführen, die darauf angewiesen sind, z. B. [foo aFunctionThatSendsAMessageToOneOfFoosSubViews].

In Ihrem aktuellen Fall wird es manchmal in der Zeit geladen und manchmal ist es nicht.

+0

Das Problem mit dieser Antwort (speziell Race-Bedingung) ist, dass dies über mehrere Tests konsistent ist. Ein Ansatz funktioniert, der andere nicht. – RonLugge

+0

Der Aufruf von 'self.view' zwingt die Ansicht _synchronous_ zu laden. – Costique

-3

wenn mich nicht alles täuscht das Problem ist, dass [foo Ansicht] versucht, eine Methode namens Ansicht zu nennen (und wenn Sie es nicht haben die Rückkehr ist nil)

auf der anderen Seite in dem Fall von foo.view, view ist eine Eigenschaft der Klasse

+2

Wenn Sie eine Eigenschaft synthetisieren, werden Getter- und Setter-Methoden erstellt. Die Standardmethoden (die 'UIViewController' für die' view' -Eigenschaft verwendet) sind '- (void) setProperty: (PropertyClass *) -Eigenschaft;' für den Setter und '- (PropertyClass *) -Eigenschaft;' für den Getter – rosslebeau

+1

Wenn Sie versucht haben, eine Methode aufzurufen, die nicht vorhanden war, stürzte die App aufgrund eines Fehlers "Unbekannter Selektor" ab. – rosslebeau

+1

yea...so ich sah durch 'UIViewController.h' und die Sache ist, dass die Eigenschaft' [self loadView] 'während' ['class' view] 'nicht – skytz

Verwandte Themen