2011-06-10 9 views
8

Tengo entendido que se llamará siempre a awakeFromNib antes de viewDidLoad.viewDidLoad y awakeFromNib timing

Así que tengo una subclase de UITableViewController, que se desarchiva de un archivo xib.

que definen estos dos métodos dentro:

- (void)awakeFromNib { 
    [super awakeFromNib]; 
    NSLog(@"awake from nib"); 
} 

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    NSLog(@"view did load"); 
} 

lo que sucede es que "hizo vista carga" muestra antes "despierta a partir de cacao" en la consola. Traté de usar un punto de interrupción en [super awakeFromNib], y presioné repetidamente F7 (Step Into), y para mi sorpresa, entró en - (void) viewDidLoad ANTES de ir a la segunda línea dentro de awakeFromNib.

¿Alguien tiene una idea de lo que está pasando aquí? Hice exactamente lo mismo en una subclase de un UIViewController regular, y las instrucciones de registro se invierten, como esperaba inicialmente ...

Respuesta

11

Para comprender este hecho, le recomiendo que vea el método loadNibNamed:owner:options: de NSBundle.

Cuando inicia un controlador de vista desde el plumín, primero que nada carga las vistas que están contenidas allí, establece propietarios de archivos propiedades según el plumín. Se llama al método viewDidLoad cuando establece la propiedad view del propietario del archivo en una de las vistas que se cargaron. Y se llama a awakeFromNib cuando están configurados todos los propietarios de archivos y las propiedades (incluida la propiedad view). Por lo tanto, tiene sentido que se llame a viewDidLoad antes que awakeFromNib.

Hope esto ayude

+2

No estoy seguro de que tengas razón. Mira esto: http: //stackoverflow.com/questions/377202/which-should-i-use-awakefromnib-or-viewdidload – Idan

+0

Entonces, ¿dónde está el conflicto con lo que estoy diciendo? El hecho es que cuando se produce una advertencia de memoria, la vista de controladores de vista (si no está visible) se establece en nulo y desasignado. Y cuando vuelve a ser visible, el controlador de vista carga su vista desde su archivo xib y establece 'self.view = viewLoadedFromXib' para que viewDidLoad se vuelva a llamar mientras no se configure de nuevo, no vuelve a llamar a awakeFromNib. – Zapko

+0

Si no me cree o no escribo claramente, puede consultar [documentación] (http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/BasicViewControllers/BasicViewControllers.html%23// apple_ref/doc/uid/TP40007457-CH101-SW19) usted mismo. De todos modos, será más útil. – Zapko

5

No creo que tengas que llamar a awakeFromNib en tu súper clase.

Verificar this.

Editar

que acaba de ejecutar una prueba rápida, aquí está el resultado:

Escenario 1: MainWindow.xib tiene una subclase UIViewController TestingAwakeFromNibViewController, que tiene su propio archivo de plumilla TestingAwakeFromNibViewController.xib.

TestingAwakeFromNibViewController tiene un Outlet UIButton llamado btn3. Prueba el siguiente código:

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    NSLog(@"Btn3 %@",btn3); 

    NSLog(@"viewDidLoad"); 
} 


-(void) awakeFromNib 
{ 
    [super awakeFromNib]; 

    NSLog(@"Btn3 %@",btn3); 

    NSLog(@"awakeFromNib"); 
} 

imprimiría:

Btn3 (null) 
AwakeFromNib 
Btn3 <UIRoundedRectButton: 0x64088e0; frame = (114 211; 72 37); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x6408890>> 
ViewDidLoad 

Escenario 2: Extracción del archivo xib, la adición de un UIView como un hijo al interior TestingAwakeFromNibViewController MainWindow.xib, y añadiendo UIButton como una subvista a la UIView (y conectando la salida del botón UI a la salida apropiada de TestingAwakeFromNibViewController).

Ahora ejecuta el código anterior podría imprimir:

Btn3 <UIRoundedRectButton: 0x4e31c30; frame = (114 211; 72 37); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x4e31be0>> 
viewDidLoad 
Btn3 <UIRoundedRectButton: 0x4e31c30; frame = (114 211; 72 37); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x4e31be0>> 
awakeFromNib 

Significado viewDidLoad antes awakeFromNib.

tercer escenario: mismo que el segundo, apenas sin llamar [super awakeFromNib];

Btn3 <UIRoundedRectButton: 0x4e0ddf0; frame = (114 211; 72 37); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x4e0dda0>> 
awakeFromNib 

Ahora viewDidLoad aún no está recibiendo llamadas.

Por lo tanto, parece que los diferentes escenarios requieren una acción diferente, y tenemos que prepararnos de acuerdo con el que estamos actuando.

+0

interesante. Si no se llama a [super awakeFromNib], no se llamará a viewDidLoad. Entonces, todo este tiempo, ¿[super awakeFromNib] llama a viewDidload? –

4

puedo crear un proyecto de prueba con la opción de aplicaciones basadas en la navegación, y añadir siguientes códigos para RootViewController.m.

- (void)awakeFromNib { 
    NSLog(@"awakeFromNib 1"); 
    [super awakeFromNib]; 
    NSLog(@"awakeFromNib 2"); 
} 

- (void)viewDidLoad { 
    NSLog(@"viewDidLoad 1"); 
    [super viewDidLoad]; 
    NSLog(@"viewDidLoad 2"); 
} 

Entonces, tengo los resultados de consola:

awakeFromNib 1 
awakeFromNib 2 
viewDidLoad 1 
viewDidLoad 2 

El -(void)viewDidLoad se llamará cuando se carga la vista de controlador. Por lo tanto, la primera vez que use self.view = ..., se invocará el -(void)viewDidLoad.

Si escribió algo como lo siguiente, entonces - (nulo) se llamará primero a viewDidLoad.

- (void)awakeFromNib { 
     /// viewDidLoad will be called 
     /// because self.view must be loaded first. 
     self.view.backgroundColor = [UIColor clearColor]; 
     [super awakeFromNib]; 
     NSLog(@"awakeFromNib 2"); 
    } 
+0

Excelente respuesta, gracias :) – evya

0

Sin ser un experto, y después de esto los mensajes, que se dan cuenta de que en un escenario ficha Controller, En el controlador de vista "niño", se ejecuta el método awakeFromNib cuando se carga el controlador pestaña (padre), pero viewDidLoad solo cuando se hace clic en "Tab".

Y, por lo tanto, entiendo que esto puede ser usado para cargar datos únicamente cuando se selecciona una ficha específica (clic)