xcode 在 AppDelegate 中,主 UIWindow 是如何实例化的?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16445709/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 03:21:59  来源:igfitidea点击:

In an AppDelegate, how is the main UIWindow instantiated?

iosobjective-cxcode

提问by user

A snippet of the default code in a Master-Detail Xcode project

Master-Detail Xcode 项目中的默认代码片段



AppDelegate.m

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

AppDelegate.h

@property (strong, nonatomic) UIWindow *window;

I am aware that @synthesize just sets the accessor methods, and no initialization happens automagically. But how does windowhave a non-nil rootViewControllerif it is never explicitly initialized? Is this just Xcode init'ing behind the scenes?

我知道@synthesize 只是设置访问器方法,并且不会自动进行初始化。但是,如果它从未显式初始化,那么如何window有一个非 nilrootViewController呢?这只是 Xcode 在幕后初始化吗?

回答by matt

From my book:

我的书中

If you choose the Storyboard option as you specify a template, the process works a little differently. The app is given a main storyboard, pointed to by the Info.plist key “Main storyboard file base name” (UIMainStoryboardFile). After UIApplicationMaininstantiates the app delegate class, it asks the app delegate for the value of its windowproperty; if that value is nil, the window is created and assigned to the app delegate's windowproperty. The storyboard's initial view controller is then instantiated and assigned to the window's rootViewControllerproperty, with the result that its view is placed in the window as its root view; the window is then sent the makeKeyAndVisiblemessage. All of that is done behind the scenes by UIApplicationMain, with no visible code whatever. That is why, in a storyboard template, the application:didFinishLaunchingWithOptions:implementation is empty.

如果您在指定模板时选择 Storyboard 选项,则该过程的工作方式略有不同。该应用程序有一个主情节提要,由 Info.plist 键“主情节提要文件基本名称”( UIMainStoryboardFile)指向。经过UIApplicationMain实例应用程序的委托类,它要求其价值的应用程序委托window财产; 如果该值为 nil,则创建窗口并将其分配给应用程序委托的window属性。然后故事板的初始视图控制器被实例化并分配给窗口的rootViewController属性,结果它的视图被放置在窗口中作为它的根视图;然后向窗口发送makeKeyAndVisible消息。所有这些都是由 幕后完成的UIApplicationMain,没有任何可见的代码。这就是为什么,在故事板模板中,application:didFinishLaunchingWithOptions:执行是空的。

回答by omz

From the UIWindowdocumentation:

UIWindow文档

Note: When you use storyboards and the Xcode app templates to create an app, a window is created for you.

注意:当您使用故事板和 Xcode 应用程序模板创建应用程序时,会为您创建一个窗口。

If you don't use storyboards, the window is explicitly created, though all the standard project templates do this out of the box. You'll see a line similar to this in the app delegate:

如果您不使用故事板,则会显式创建窗口,尽管所有标准项目模板都是开箱即用的。您将在应用程序委托中看到与此类似的一行:

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

Using storyboards, the window is created behind the scenes when the main storyboard is loaded (see the View Controller Programming Guidefor more info).

使用情节提要,当加载主情节提要时在幕后创建窗口(有关更多信息,请参阅视图控制器编程指南)。

回答by rdelmar

From Apple's docs (in "Using View Controllers in Your App"):

来自 Apple 的文档(在“在你的应用程序中使用视图控制器”):

The Main Storyboard Initializes Your App's User Interface

The main storyboard is defined in the app's Information property list file. If a main storyboard is declared in this file, then when your app launches, iOS performs the following steps:

It instantiates a window for you. It loads the main storyboard and instantiates its initial view controller. It assigns the new view controller to the window's rootViewController property and then makes the window visible on the screen.

主故事板初始化您的应用程序的用户界面

主故事板在应用程序的信息属性列表文件中定义。如果在此文件中声明了主故事板,那么当您的应用程序启动时,iOS 会执行以下步骤:

它为您实例化一个窗口。它加载主故事板并实例化其初始视图控制器。它将新的视图控制器分配给窗口的 rootViewController 属性,然后使窗口在屏幕上可见。

回答by Undo

In your Storyboard, there is a little arrow you can drag around:

在您的故事板中,您可以拖动一个小箭头:

arrow

箭

If you were using xibs/nibs instead, the 'Main Interface' field would be filled out.

如果您使用的是 xibs/nibs,则将填写“主界面”字段。

interface

界面

In the end, yep, it's iOS/Xcode magic.

最后,是的,这是 iOS/Xcode 的魔法。

回答by Mythlandia

The above answers only who sets the window variable without answering the main questions: "But how does window have a non-nil rootViewController if it is never explicitly initialized? Is this just Xcode init'ing behind the scenes?" and seem to suggest that there is magic afoot. Not a satisfactory answer for me, and so with a little digging, all becomes clear.

上面只回答了谁设置了 window 变量而没有回答主要问题:“但是如果 window 从未显式初始化,它如何具有非 nil rootViewController?这只是 Xcode 在幕后初始化吗?” 并且似乎暗示魔法正在发生。对我来说不是一个令人满意的答案,所以稍微挖掘一下,一切都会变得清晰。

The generated code defines AppDelegate as

生成的代码将 AppDelegate 定义为

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

When you search the project, there is no other reference to window, so apparently it should remain nil, but actually is set to the correct value (by the methods outlined above). The "magic" is that AppDelegate conforms to the UIApplicationDelegate which includes an declaration:

当您搜索项目时,没有其他对 window 的引用,因此显然它应该保持为零,但实际上已设置为正确的值(通过上述方法)。“神奇”在于 AppDelegate 符合 UIApplicationDelegate ,其中包括一个声明:

    optional public var window: UIWindow? { get set }

Part of conforming to the UIApplicationDelegate is the redeclaration of the public variable window. When the underlying Application references the variable windowin the protocol, it is actually linked to the variable windowin our class. When the calling Application updates that variable windowin the protocol, it is actually updating our variable window. So when we need to access the value in our program it is ready and waiting.

符合 UIApplicationDelegate 的一部分是公共变量window的重新声明。当底层Application引用协议中的变量window时,实际上是链接到我们类中的变量window。当调用应用程序更新协议中的变量window时,它实际上是在更新我们的变量window。因此,当我们需要访问程序中的值时,它已准备就绪并在等待。

This is notXcode magic, but an integral part of the Swift language. When using protocols we can employ the same techniques in our own Swift programs. This is just the same as our implementations of various functions in our classes which we do all the time: e.g. UIApplicationDelegate defines

不是Xcode 的魔法,而是 Swift 语言不可或缺的一部分。在使用协议时,我们可以在我们自己的 Swift 程序中使用相同的技术。这与我们在类中的各种函数的实现是一样的,我们一直在这样做:例如 UIApplicationDelegate 定义

optional public func applicationDidEnterBackground(_ application: UIApplication)

optional public func applicationDidEnterBackground(_ application: UIApplication)

so we can write our own implementation which is then "magically" called!

所以我们可以编写我们自己的实现,然后“神奇地”调用它!

For completeness, note the @UIApplicationMaintag on the class. This defines the entry point for the application and is what makes everything work together. The actual class name is irrelevant, and can be given any name you require, as long as it is of type UIResponder and conforms to the UIApplicationDelegate.

为完整起见,请注意类上的@UIApplicationMain标记。这定义了应用程序的入口点,并且是使一切协同工作的原因。实际的类名是无关紧要的,只要它是 UIResponder 类型并符合 UIApplicationDelegate 的,就可以给它任何你需要的名字。