objective-c - publicidad - ios 12
¿Por qué la función main() de una aplicación iPhone nunca tiene la oportunidad de terminar? (6)
Considere el siguiente método main()
que encontraría en la mayoría de las aplicaciones de iPhone:
int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
En cada aplicación de iPhone que he ejecutado en Simulator con estos (incluidos varios proyectos de muestra proporcionados por Apple), el hilo nunca sale de UIApplicationMain()
y cualquier código restante en main()
nunca se ejecuta. ¿Es este comportamiento esperado?
He verificado que las sentencias posteriores a UIApplicationMain()
nunca se ejecutan al recorrer el código con un depurador. Cuando el usuario detiene una aplicación (presionando el botón "Inicio", por ejemplo), el seguimiento de pila resultante muestra que [UIApplication _terminateWithStatus:]
se llama finalmente. Esta función llama al método applicationWillTerminate de tu delegado de applicationWillTerminate:
. Una vez que termina, [UIApplication _terminateWithStatus:]
parece matar / salir del hilo.
¿Alguien puede confirmar que así es como se supone que main()
funciona, o al menos confirmar el mismo comportamiento en su máquina?
¿Después de [la liberación del grupo] no hay nada para iniciar sesión?
Después de llamar a la función UIApplicationMain
, su aplicación se inicia (estableciendo un runloop, etc.) y todo el trabajo debe realizarse fuera del contexto de main (si necesita ejecutarlo en main, hágalo antes de ese punto). Al salir de una aplicación, generalmente es más eficiente permitir que el sistema operativo limpie la memoria.
La pregunta original fue: " ¿Por qué la función main () de una aplicación de iPhone nunca tiene la oportunidad de terminar? "
Respuesta corta: debido a que UIApplicationMain () está codificado de manera tal que nunca regresa.
Después de hacer varias pruebas en Simulator y en el dispositivo, y pedirle a otro desarrollador que haga las mismas pruebas, he confirmado que UIApplicationMain nunca regresa. Cuando el usuario finaliza una aplicación normalmente presionando el botón Inicio, el programa finaliza finalmente dentro de un método UIAplication no publicado llamado _terminateWithStatus. Este método llama a exit (0).
Este comportamiento coincide con el de la función NSApplicationMain (que es la versión de AppKit / Cocoa de la función UIApplicationMain). La documentación de NSApplicationMain () indica claramente que nunca volverá.
He enviado un error (6600198) a Apple solicitando que la documentación oficial (y la plantilla de Xcode para main.m) se corrijan para indicar que UIApplicationMain () nunca regresa. Si bien esto no es un problema funcional, la plantilla y los documentos actuales son engañosos.
Gracias a todos por su aporte y lluvia de ideas.
Tratar:
int main(int argc, char *argv[])
{
NSLog(@"Step 0");
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLog(@"Step 1");
int retVal = UIApplicationMain(argc, argv, nil, nil);
NSLog(@"Step 2");
[pool release];
NSLog(@"Step 3");
return retVal;
}
Es posible que el lanzamiento del grupo impida un registro posterior, en cuyo caso obtendría el paso 2 pero no el paso 3.
Si el paso 2 no se está imprimiendo, es casi seguro que algo está mal con UIApplicationMain, existe la posibilidad de que no vuelva, por lo tanto, coloque las declaraciones NSLog (paso 1.1, paso 1.2, ...) en varios puntos y ejecute hasta encontrar el último mensaje registrado
Mantenga la exploración hacia abajo (Paso 1.7.1, 1.7.2, .... 1.7.6.3.2, ...) - con el tiempo, podrá rastrear la línea exacta (independientemente de la profundidad de la jerarquía de llamadas) cuando los mensajes de registro deja de registrarte y esa línea será tu culpable (ya sea "apagando" el registro o saliendo sin regresar normalmente).
Un fragmento más que encontré en la web:
=====
Cuando usas esta línea:
int retVal = UIApplicationMain(argc, argv, @"MyApp", @"MyApp");
La primera MyApp es su clase principal de delegados de aplicaciones. El segundo es la clase a la que SpringBoard envía notificaciones táctiles.
Además, si usa el SDK y tiene un plumín principal definido en Info.plist, puede dejar la llamada como sigue:
int retVal = UIApplicationMain(argc, argv, nil, nil);
como todo lo que se cubrirá cuando crees tus xibs.
=====
Ahora no sé lo suficiente sobre el desarrollo de iPhone (específicamente xibs) para saber lo que significa el último bit (o si lo has configurado correctamente), pero suena como otra fase de compilación.
Sin embargo, mi primer pensamiento al leer eso es que Springboard llamará a su clase de delegado cuando se presionen los botones para pedirle que haga algo (como cerrar con gracia). Si no puede preguntarle (es decir, sin delegado), es probable que tenga derecho a cerrarlo como lo considere oportuno, como con [UIApplication _terminateWithStatus:]
.
En el mundo de Windows, probablemente envíe un mensaje de renuncia a la ventana principal, pero, como digo, el desarrollo de iPhone puede ser diferente.
Aún así, es una avenida para investigar. Me interesaría ver qué llamadas se hicieron a un delegado si me proporcionó uno. El código incluido con el fragmento anterior tenía esto:
@implementation MyApp
- (void) applicationDidFinishLaunching:(id)unused {
rect = [ UIHardware fullScreenApplicationContentRect ];
rect.origin.x = 0.0f;
rect.origin.y = 0.0f;
window = [ [ UIWindow alloc ] initWithContentRect: rect ];
[ window makeKeyAndVisible ];
view = [ [ MyAppView alloc ] initWithFrame: rect ];
[ window setContentView: view ];
}
- (void) dealloc {
[ window release ];
[ view release ];
[ super dealloc ];
}
Entonces, tal vez un delegado con dealloc()
es el secreto para lograr que vuelva a salir a main()
. ¿Por qué no le das una oportunidad? Puede acercarlo más a su objetivo, incluso si no resuelve el problema central.
tratando de usar fprintf y ver qué pasa
int main(int argc, char *argv[])
{
/*
...
same as above
...
*/
[pool release];
char file_name = "/tmp/log"
FILE *file = fopen(file_name, "w");
fprintf(file_name, "END/n");
}
y dinos que sucede
También pensé que la forma más fácil de verificar era establecer un punto de quiebre justo a la vuelta
en gdb do
b main.c:x
donde x es el número de línea de la declaración de devolución
Tengo esa experiencia no retorno también. Y han establecido puntos de ruptura para verificar exactamente como dijo Clint.
wisequark tiene un buen punto.
gran tema me hace sentir más cómodo que no soy el único que tiene la pregunta.