mac for descargar ios objective-c xcode

ios - for - En un AppDelegate, ¿cómo se crea una instancia de la UIWindow principal?



xcode for windows (5)

Un fragmento del código predeterminado en un proyecto Xcode de Master-Detail

AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController; // *** here *** MasterViewController *controller = (MasterViewController *)navigationController.topViewController; controller.managedObjectContext = self.managedObjectContext; return YES; }

AppDelegate.h

@property (strong, nonatomic) UIWindow *window;

Soy consciente de que @synthesize solo establece los métodos de acceso, y que no se realiza ninguna inicialización automágicamente. Pero, ¿cómo tiene la window un rootViewController no nulo si nunca se inicializa explícitamente? ¿Esto es solo el inicio de Xcode detrás de escena?


De mi libro :

Si elige la opción Guión gráfico al especificar una plantilla, el proceso funciona de manera un poco diferente. La aplicación recibe un guión gráfico principal, señalado por la clave Info.plist "Nombre de la base de archivos del guión gráfico principal" ( UIMainStoryboardFile ). Después de que UIApplicationMain instancia de la clase de delegado de la aplicación, solicita al delegado de la aplicación el valor de su propiedad de window ; si ese valor es nulo, la ventana se crea y se asigna a la propiedad de window del delegado de la aplicación. El controlador de vista inicial del guión gráfico se rootViewController instancia y se asigna a la propiedad rootViewController la ventana, con el resultado de que su vista se coloca en la ventana como su vista raíz; la ventana se envía al mensaje makeKeyAndVisible . Todo esto se hace detrás de escena por UIApplicationMain , sin ningún código visible. Por eso, en una plantilla de guión gráfico, la application:didFinishLaunchingWithOptions: implementación está vacía.


De la documentación de UIWindow :

Nota: cuando utiliza guiones gráficos y las plantillas de la aplicación Xcode para crear una aplicación, se crea una ventana para usted.

Si no utiliza los guiones gráficos, la ventana se crea explícitamente, aunque todas las plantillas de proyecto estándar lo hacen de forma inmediata. Verás una línea similar a esta en el delegado de la aplicación:

self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];

Al usar guiones gráficos, la ventana se crea entre bastidores cuando se carga el guión gráfico principal (consulte la Guía de programación de View Controller para obtener más información).


De los documentos de Apple (en "Uso de controladores de visualización en su aplicación"):

El guión gráfico inicializa la interfaz de usuario de su aplicación

El guión gráfico principal se define en el archivo de lista de propiedades de información de la aplicación. Si se declara un guión gráfico principal en este archivo, cuando se inicie la aplicación, iOS realiza los siguientes pasos:

Crea una ventana para ti. Carga el guión gráfico principal y crea una instancia de su controlador de vista inicial. Asigna el nuevo controlador de vista a la propiedad rootViewController de la ventana y luego hace que la ventana sea visible en la pantalla.


En tu Guión gráfico, hay una pequeña flecha que puedes arrastrar:

Si estuviera utilizando xibs / nibs en su lugar, el campo ''Interfaz principal'' se completaría.

Al final, sí, es la magia de iOS / Xcode.


Las respuestas anteriores solo responden quién configura la variable de ventana sin responder las preguntas principales: "¿Pero cómo tiene la ventana un controlador de control de raíz no nulo si nunca se inicializa explícitamente? ¿Esto es solo el inicio de Xcode detrás de escena?" y parece sugerir que hay magia en marcha. No es una respuesta satisfactoria para mí, y así, con un poco de investigación, todo se vuelve claro.

El código generado define AppDelegate como

@UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? ... }

Cuando busca en el proyecto, no hay otra referencia a la ventana, por lo que aparentemente debería permanecer en cero, pero en realidad se establece en el valor correcto (según los métodos descritos anteriormente). La "magia" es que AppDelegate se ajusta a la UIApplicationDelegate que incluye una declaración:

optional public var window: UIWindow? { get set }

Parte de la conformidad con UIApplicationDelegate es la redeclaración de la ventana de variable pública. Cuando la Aplicación subyacente hace referencia a la ventana variable en el protocolo, en realidad está vinculada a la ventana variable en nuestra clase. Cuando la aplicación que llama actualiza esa ventana de variable en el protocolo, en realidad está actualizando nuestra ventana de variable. Entonces, cuando necesitamos acceder al valor en nuestro programa, está listo y en espera.

Esto no es magia de Xcode, sino una parte integral del lenguaje Swift. Al usar protocolos, podemos emplear las mismas técnicas en nuestros propios programas Swift. Esto es lo mismo que nuestras implementaciones de varias funciones en nuestras clases que hacemos todo el tiempo: por ejemplo, UIApplicationDelegate define

optional public func applicationDidEnterBackground(_ application: UIApplication)

¡así podemos escribir nuestra propia implementación que luego se llama "mágicamente"!

Para completar, note la etiqueta @UIApplicationMain en la clase. Esto define el punto de entrada para la aplicación y es lo que hace que todo funcione en conjunto. El nombre real de la clase es irrelevante, y se le puede dar cualquier nombre que necesite, siempre y cuando sea del tipo UIResponder y se ajuste a la UIApplicationDelegate.