2012-03-28 11 views
7

Per puro caso ho scoperto che chiamare [bar.view addSubview:[foo view]] non funziona, ma [bar.view addSubview:foo.view] fa nel seguente codice.Perché la vista [foo] si comporta diversamente da foo.view nel mio codice?

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

(L'ultima linea è perché foo ha alcuni sotto-vista che devono essere impostati prima di eseguire -. In particolare, un UIWebView Se non sono stati istanziati prima che il messaggio viene inviato, il messaggio venti fino andando a nil Con foo)

ho pensato che questi due erano funzionalmente identico - che foo.view chiama lo stesso getter che [foo view] fa, ma in pratica non è questo il caso..; la sintassi del punto ottiene i risultati desiderati, mentre l'uso delle parentesi termina inviando il messaggio a nil.

Se mi avessi chiesto dieci minuti fa, ti avrei detto che la differenza tra le due espressioni era "sintassi e nient'altro". Dato che sono chiaramente sbagliato, ho bisogno di capire come ho sbagliato o ho intenzione di inciampare su di esso di nuovo.

+0

Hai provato a confrontare l'output effettivo di '[foo view]' e 'foo.view'? Essi devono essere uguali. – Costique

+0

In realtà, si. Ho usato NSLog (@ "View Info:% @", [foo view]) e una dichiarazione simile a foo.view. Identico - anche quando li inverto. Sembra che restituiscano esattamente la stessa cosa. – RonLugge

+1

Quando si visualizza il codice nell'Assistente Editor di Xcode e si sceglie "Assemblaggio" dal menu a discesa dello smoking, si osservano differenze tra l'uso della sintassi e delle parentesi? –

risposta

3

Sono funzionalmente equivalenti. Penso che questa sia una condizione di gara. Quando si chiama per la prima volta foo.view in tale codice, la vista non è ancora stata caricata e una chiamata viene inviata a [foo loadView]. Non puoi essere sicuro che la vista sia caricata fino a quando non viene chiamato [foo viewDidLoad] o foo.isViewLoaded == YES.

È necessario attendere che la vista sia caricata prima di eseguire qualsiasi azione che si basi su di essa, come ad esempio [foo aFunctionThatSendsAMessageToOneOfFoosSubViews].

Nel tuo caso attuale, a volte si carica in tempo e talvolta non lo è.

+0

Il problema con questa risposta (in particolare, condizioni di competizione) è che questo è coerente su più test. Un approccio funziona, l'altro no. – RonLugge

+0

La chiamata a 'self.view' forza la vista a caricare _synchronously_. – Costique

-3

se non mi sbaglio il problema è che [vista foo] tenta di chiamare una vista metodo denominato (e se non ce l'hai il ritorno è pari a zero)

d'altra parte, nel caso di foo.view, view è una proprietà della classe

+2

Quando sintetizzi una proprietà, crea metodi getter e setter. I metodi predefiniti (che 'UIViewController' usa per la proprietà' view') sono '- (void) setProperty: (PropertyClass *) proprietà;' per il setter e '- (PropertyClass *) proprietà;' per il getter – rosslebeau

+1

Inoltre, se hai provato a chiamare un metodo che non esisteva, l'app si arrestava in modo anomalo a causa di un errore di Selettore non riconosciuto. – rosslebeau

+1

sì..so ho guardato attraverso 'UIViewController.h' e il fatto è che la proprietà chiama' [auto loadView] 'mentre' ['class' view] 'non è – skytz

Problemi correlati