rojo - mi iphone no reconoce el cargador
Orden de inicialización y carga de UIViewController (5)
Soy bastante nuevo en la programación de IU en la Mac y el iPhone, y me encontré con algo que me deja algo desconcertado.
Un UIViewController tiene 3 métodos que implican la inicialización de este y su vista:
- init (y métodos tipo init)
- loadView
- viewDidLoad (método delegado)
Esperaría que ocurrieran en el orden anterior. El primer UIViewController es asignado por algún otro objeto, luego se llama inmediatamente a init (o a algún otro método init, como initWithStyle).
Solo cuando se inicialice el objeto esperaría que llamara a su propia función loadView, después de lo cual la vista, una vez cargada, llama al método de delegado viewDidLoad.
Esto no sucede, por ejemplo:
@implementation UIViewControllerSubclass
- (id)init {
NSLog(@"0");
if (self = [super init]) {
NSLog(@"1");
}
return self;
}
- (void)loadView {
[super loadView];
NSLog(@"2");
}
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"3");
}
@end
Produce la salida de la consola:
0
2
3
1
Los métodos loadView y viewDidLoad, por lo tanto, no pueden realizar llamadas de delegado, ya que el delegado generalmente se establece después de la llamada a [superinicio], que (como se muestra arriba) se llama después de ejecutar loadView y viewDidLoad:
UIViewControllerSubClass *someViewController = [[UIViewControllerSubclass alloc] init];
[viewController setDelegate:self];
Si quiero ejecutar el código que configura ViewController de alguna manera, notificando al delegado como va, ¿debería residir el código en el método init? ¿No es la razón por la que loadView existing permite que dicho código se ejecute en el momento apropiado?
Me parece que tendré que crear un nuevo método initWithDelegate que establezca el delegado ivar antes de llamar a [superinicial], ¿es correcto o voy por el camino equivocado?
Gracias por adelantado :)
El initWithNibName:bundle: es el inicializador designado para la clase UIViewController.
Intente anular y usarlo en lugar de init:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
}
return self;
}
...
UIViewControllerSubClass *someViewController = [[UIViewControllerSubclass alloc] initWithNibName:@"UIViewControllerSubclass" bundle:nil];
El sistema de carga de vista en el iPhone funciona así:
Cuando inicializa un controlador de vista (ya sea con -init o -initWithNibName: bundle :), en realidad no crea e inicializa la vista. Cuando llama -view por primera vez, llama -loadView. De forma predeterminada, -loadView solo carga la vista desde el archivo xib (nibName). Sin embargo, si anulas esto, eres responsable de crear la vista y asignarla a la propiedad de vista del controlador de vista. Como ejemplo:
- (void)loadView
{
UIView *view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
// add subviews
self.view = view;
[view release];
}
Cada vez que crea la vista, que es diferente de la vista que se hace visible y se muestra en pantalla , llama a -viewDidLoad. (-viewDidAppear / -viewDidDisappear es para la visibilidad de la vista en pantalla)
Como ya estamos fuera de la ruta, consideremos la gestión de la memoria. Cuando la vista está fuera de la pantalla, el sistema establecerá automáticamente la propiedad de vista de un controlador de vista en cero. El problema es que todas las subvistas de esa vista tienen filtraciones. ¿Cómo es eso? Bueno, el recuento de retención para cada subvista es 2 (las vistas retienen las subvistas, y su controlador de vista tiene una salida / ivar). Cuando la vista es nula, el conteo retenido de esa vista es 1. No tiene sentido que una vista se quede si no se muestra una vista, por lo que la configura en nil en -viewDidUnload (que es un gancho para cada vez que la vista se establece en nil).
Gerry3 tiene razón. Esto también me confunde a mí también. Consulte los documentos en los inicializadores designados .
También tenga en cuenta que si su controlador es creado por un plumín que está siendo cargado, entonces solo se llamará a initWithCoder. loadView no se llama tampoco en ese caso.
Debido a esto, parece que la mayoría del código que he visto hace la mayoría de las inicializaciones en cosas como viewDidLoad, aunque parezca incorrecto, pero parece ser el mejor método que se llama en ambos casos donde se carga algo en un plumín y se crea programáticamente.
Pero la razón por la cual esto parece estar fuera de orden es que [superinicial] está llamando a loadView, etc.
Tomando la sugerencia de @Nimrod, hice algo como:
-(void)viewDidLoad
{
// Init code here
}
No sé si esto puede causar problemas con la pérdida de memoria, pero mirando los documentos de Apple no parece crear ningún ciclo:
Esto fue tomado de: http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/ViewLoadingandUnloading/ViewLoadingandUnloading.html#//apple_ref/doc/uid/TP40007457-CH10-SW1
-(void)awakeFromNib
{
}
solo se invoca si está usando storyboard para almacenar ViewController dibujado en el storyboard Nib --- significa paquete de interfaz.
la secuencia correcta es
-(void)initWithCoder
-(void)awakefromNib //(if story board is used)
or
-(void)loadView----() //if manually generating the view contoller
-(void)viewDidLoad-----(called only once in the life cycle of viewController)
-(void)viewWillAppear
-(void)viewDidAppear
Mientras se mueve a un nuevo ViewController
-(void)viewWillDisappear
-(void)viewDidDisappear
Al regresar al primer ViewController
-(void)viewWillAppear
-(void)viewDidAppear