Liberación del controlador de vista principal (iOS)

He buscado esto en el sitio de Apple y parece que solo puedo encontrar documentación usando Storyboards o Navigation Controllers, ninguno de los cuales estoy usando. Es una pregunta increíblemente sencilla sobre la gestión de la memoria.

Creé una aplicación completamente en blanco. En la función didFinishLaunchingWithOptions de mi AppDelegate, estoy creando una instancia de un controlador de vista que he creado. Mi diseño (que en sí mismo podría ser un problema) es tener una relación 1: 1 entre los controladores de vista y las vistas.

Entonces, el menú principal de mi aplicación, que es una plataforma de lanzamiento para todo, está en MenuViewController.h/m.

En .h:

MenuViewController *m;

En m:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    // Override point for customization after application launch.
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];

    m = (MenuViewController *)[[MenuViewController alloc] init];
    m.window = self.window;
    [m doStuff]; // handful of functions, not actually called this
    //[m release]; // doesn't make sense to me
    return YES;
}

Aquí es donde estoy confundido. Quiero que esto exista básicamente durante todo el ciclo de vida de la aplicación. Pero también tengo la impresión de que debería (en el ámbito de la función actual) liberar todo lo que asigne. Si lo necesita más allá de eso, debe conservarlo en otro lugar primero. ¿No es esto cierto?

Mi pregunta fundamental es... ¿dónde debo lanzar este controlador de vista? ¿Hay algo más que haya dicho que parezca fuera de lugar?

preguntado el 22 de mayo de 12 a las 21:05

¿Por qué no usaste el conteo automático de referencias? (Tal vez podrías lanzarlo en applicationWillTerminate:application del AppDelegate) -

Lo soltará antes de pasar a la siguiente vista. También puede hacerlo en el método viewDidUnload o dealloc -

2 Respuestas

La inicialización es incorrecta. No asigna una ventana al controlador, asigna un controlador a la ventana:

    // window creation code here
    ...
    m = [[MenuViewController alloc] init];
    [window setRootViewController:m]; // window does retain for m
    [m release]; // so we release it here
    [self.window makeKeyAndVisible];
    return YES
}

contestado el 22 de mayo de 12 a las 21:05

RootViewController para mí implica uno. ¿Es un diseño incorrecto o deficiente tener un controlador de vista para cada "pantalla" en mi aplicación? Actualmente tengo uno para el Menú principal, la pantalla de carga, una pantalla para crear usuarios, una pantalla para administrar otros datos, etc. - JamesB41

Así es exactamente como se supone que debes hacerlo. Por supuesto, en algunos casos puede ser razonable usar una subclase de controlador de vista más de una vez, pero para pantallas que son muy diferentes en naturaleza y función, generalmente tiene una subclase de controlador de vista separada. - BateristaB

@ JamesB41 es por eso que la mayoría de las aplicaciones tienen controladores de barra de pestañas o controladores de navegación que permiten presentar algunos controladores de vista o tener una navegación detallada. - Eimantas

Ok, pero ¿puede ser solo un RootViewController? Si estoy mostrando otra parte de pantalla completa de mi aplicación, ¿configuro el nuevo controlador como RootViewController? ¿Qué hace eso, además de traerlo al frente (supongo?)? - JamesB41

Sí, solo puede haber un controlador de vista raíz. Y si debe cambiarlo para mostrar otra pantalla, está haciendo algo mal. - Eimantas

Tienes razón. En general, debe publicar cualquier cosa que cree en un alcance. Pero en este caso, desea la propiedad del controlador de vista. En este caso, debe soltar el objeto en el dealloc método del delegado de su aplicación:

- (void)dealloc {
    [m release];
    [super dealloc];
}

Alternativamente, podría definir un @property para su controlador de vista con bandera de retención y luego haga esto:

MenuViewController *viewController = [[MenuViewController alloc] init];
self.m = viewController;
[viewController release];

Por cierto, no es necesario enviar a MenuViewController en ningún caso.

EDITAR: Me perdí por completo que no agregue su controlador de vista a su ventana. Buen punto @Eimantas.

contestado el 22 de mayo de 12 a las 21:05

Solo necesitaba emitirlo porque después llamé a un método desde AppDelegate y estaba lanzando una advertencia. - JamesB41

¿Importó el encabezado de su controlador de vista en el delegado de su aplicación? Si su variable (m) es del tipo MenuViewController (que es según su publicación) y el valor que le está pasando es del mismo tipo, entonces no necesita emitir. Esa advertencia tenía que tener otra razón. - BateristaB

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.