2013-05-08 8 views
17

Ein Ausschnitt des Standard-Code in einem Projekt Xcode Master-DetailWie wird das Haupt-UIWindow in einem AppDelegate instanziiert?


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; 

Ich bin mir bewusst, dass @synthesize nur Sätze die Accessor-Methoden, und keine Initialisierung geschieht automatisch. Aber wie hat window eine nicht-Null rootViewController, wenn es nie explizit initialisiert wird? Startet Xcode nur hinter den Kulissen?

Antwort

21

Von my book:

Wenn Sie die Option wählen, Storyboard, wie Sie eine Vorlage angeben, funktioniert der Prozess ein wenig anders. Die App erhält ein Haupt-Storyboard, auf das der Info.plist-Schlüssel "Haupt-Storyboard-Datei-Basisname" (UIMainStoryboardFile) zeigt.Nachdem UIApplicationMain die App-Delegate-Klasse instanziiert hat, fragt sie den App-Delegaten nach dem Wert seiner window-Eigenschaft. Wenn dieser Wert gleich null ist, wird das Fenster erstellt und der Eigenschaft window des App-Delegierten zugewiesen. Der ursprüngliche View-Controller des Storyboards wird dann instanziiert und der Eigenschaft rootViewController des Fensters zugewiesen, mit dem Ergebnis, dass seine Ansicht im Fenster als Root-Ansicht platziert wird. Das Fenster sendet dann die Nachricht makeKeyAndVisible. All das geschieht hinter den Kulissen von UIApplicationMain, ohne sichtbaren Code. Aus diesem Grund ist in einer Storyboard-Vorlage die application:didFinishLaunchingWithOptions: Implementierung leer.

+0

Das antwortet sehr gut, wer die Fenstereigenschaft aktualisiert, aber siehe meine Antwort unten für wie es gemacht wird. – Mythlandia

1

In Ihrem Storyboard gibt es einen kleinen Pfeil Sie herum ziehen:

Feld ausgefüllt werden würde

arrow

Wenn Sie stattdessen xibs/Nibs wurde unter Verwendung des ‚Haupt Interface‘.

interface

Am Ende yep, es ist iOS/Xcode Magie.

+2

Nichts "Magie" darüber. Das ist nicht gut, einem Fragesteller zu erzählen! – matt

+1

Wenn das keine Magie ist, dann ist nichts. Es ist kein Geheimnis, dass alles zu einer Assembler-Anweisung zerfällt, aber wenn ein grafischer Pfeil bedeutet, dass Code kompiliert wird, ohne dass ich ihn schreibe (oder sehe), ist es sicher, diese Magie zu nennen. – user

+0

Dieser Pfeil ist vorhanden, weil Sie diesen Ansichts-Controller als anfänglichen Ansichts-Controller festgelegt haben. All dieser Pfeil gibt einen weiteren Hinweis auf diese Tatsache. Die Laufzeit ruft 'instantiateInitialViewController' auf - was genau in der UIStoryboard-Dokumentation steht. Immer noch keine Magie. – matt

2

Von docs Apples (in "Verwendung von View-Controller in Ihrer App"):

Die Hauptstoryboard-App-Benutzeroberfläche

Das Hauptstoryboard Initialisiert in den Informationen des App-Property-List-Datei definiert ist. Wenn in dieser Datei ein Haupt-Storyboard deklariert ist, führt iOS beim Starten der App die folgenden Schritte aus:

Es stellt ein Fenster für Sie bereit. Es lädt das Haupt-Storyboard und instanziiert seinen ursprünglichen View-Controller. Er weist der Eigenschaft rootViewController des Fensters den neuen View-Controller zu und macht das Fenster dann auf dem Bildschirm sichtbar.

4

Vom UIWindow documentation:

Hinweis: Wenn Sie Storyboards und die Xcode App-Vorlagen verwenden, um eine App zu erstellen, wird ein Fenster für Sie erstellt wird.

Wenn Sie keine Storyboards verwenden, wird das Fenster explizit erstellt, obwohl dies bei allen Standardprojektvorlagen standardmäßig erfolgt. Sie werden eine Zeile wie diesen in der AppDelegate sehen:

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

Storyboards verwendet, wird das Fenster hinter den Kulissen erstellt, wenn der Hauptstoryboard (siehe View Controller Programming Guide für weitere Informationen) geladen wird.

0

Die oben genannten Antworten nur wer das Fenster Variable setzt, ohne die wichtigsten Fragen zu beantworten: „Aber wie funktioniert Fenster haben einen nicht-Null RootViewController wenn es nie explizit initialisiert wird, ist dies nur Xcode init'ing hinter den Kulissen? " und scheinen darauf hinzuweisen, dass Magie im Gange ist. Keine befriedigende Antwort für mich, und mit ein wenig Graben wird alles klar.

Der generierte Code AppDelegate als

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

definiert Wenn Sie das Projekt suchen, gibt es keine andere Referenz auf Fenster, so offenbar sollte es bleiben null, aber tatsächlich ist auf den korrekten Wert (durch die Verfahren eingestellt oben skizziert). Der „Magic“ ist, dass AppDelegate zum UIApplicationDelegate entspricht, die eine Angabe enthält:

optional public var window: UIWindow? { get set } 

Teil zum UIApplicationDelegate konformen wird die Neudeklaration des öffentlichen variable Fenster. Wenn die zugrunde liegende Anwendung im Protokoll auf die Variable window verweist, ist sie tatsächlich mit der Variablen Fenster in unserer Klasse verknüpft. Wenn die aufrufende Anwendung diese Variable Fenster im Protokoll aktualisiert, aktualisiert sie tatsächlich unsere Variable Fenster. Wenn wir also auf den Wert in unserem Programm zugreifen müssen, ist es bereit und wartet.

Dies ist nicht Xcode Magie, sondern ein integraler Bestandteil der Swift Sprache. Bei der Verwendung von Protokollen können wir die gleichen Techniken in unseren eigenen Swift-Programmen verwenden. Dies ist genau das gleiche wie unsere Implementierungen von verschiedenen Funktionen in unseren Klassen, die wir die ganze Zeit machen: z.B. UIApplicationDelegate definiert

optional public func applicationDidEnterBackground(_ application: UIApplication)

so können wir unsere eigene Implementierung schreiben, die dann „magische Weise“ genannt!

Der Vollständigkeit halber beachten Sie das @ UIApplicationMain Tag auf der Klasse. Dies definiert den Einstiegspunkt für die Anwendung und sorgt dafür, dass alles zusammenarbeitet. Der tatsächliche Klassenname ist irrelevant und kann einen beliebigen Namen erhalten, so lange er vom Typ UIResponder ist und dem UIApplicationDelegate entspricht.

Verwandte Themen