Master-Detail Xcode项目中默认代码的片段
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;
我知道@synthesize只设置了访问器方法,并且没有自动执行初始化。但如果window
从未明确初始化,rootViewController
如何具有非零{{1}}?这只是Xcode在幕后启动吗?
答案 0 :(得分:24)
来自my book:
如果在指定模板时选择了Storyboard选项,则该过程的工作方式略有不同。该应用程序有一个主要的故事板,由Info.plist键“主故事板文件基本名称”(
UIMainStoryboardFile
)指向。在UIApplicationMain
实例化app委托类之后,它会向应用委托询问其window
属性的值;如果该值为nil,则创建窗口并将其分配给app delegate的window
属性。然后将故事板的初始视图控制器实例化并分配给窗口的rootViewController
属性,结果是其视图作为其根视图放置在窗口中;然后向窗口发送makeKeyAndVisible
消息。所有这些都是在UIApplicationMain
的幕后完成的,没有任何可见的代码。这就是为什么在故事板模板中,application:didFinishLaunchingWithOptions:
实现是空的。
答案 1 :(得分:4)
注意:当您使用故事板和Xcode应用程序模板创建应用程序时,会为您创建一个窗口。
如果您不使用故事板,则会显式创建窗口,但所有标准项目模板都是开箱即用的。您将在应用委托中看到与此类似的行:
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
使用故事板,在加载主故事板后,将在幕后创建窗口(有关详细信息,请参阅View Controller Programming Guide)。
答案 2 :(得分:2)
来自Apple的文档(在“在应用程序中使用视图控制器”):
主故事板初始化您应用的用户界面
主要故事板在应用程序的信息属性列表文件中定义。如果在此文件中声明了主故事板,那么当您的应用程序启动时,iOS将执行以下步骤:
它为您实例化一个窗口。 它加载主故事板并实例化其初始视图控制器。 它将新视图控制器分配给窗口的rootViewController属性,然后在屏幕上显示该窗口。
答案 3 :(得分:1)
在你的故事板中,你可以拖动一个小箭头:
如果您使用的是xibs / nibs,那么主界面就是'字段将被填写。
最后,是的,它是iOS / Xcode魔术。
答案 4 :(得分:1)
以上答案只有谁设置窗口变量而没有回答主要问题:“但是如果窗口永远没有显式初始化,那么窗口如何有一个非零的rootViewController?这只是Xcode在幕后初始化吗?”而且似乎暗示着有魔力在进行。对我来说不是一个令人满意的答案,所以通过一点挖掘,一切都变得清晰。
生成的代码将AppDelegate定义为
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
...
}
当你搜索项目时,没有其他对窗口的引用,所以显然它应该保持为零,但实际上设置为正确的值(通过上面概述的方法)。 “神奇”是AppDelegate符合包含声明的UIApplicationDelegate:
optional public var window: UIWindow? { get set }
符合UIApplicationDelegate的部分是公共变量 window 的重新声明。当底层应用程序引用协议中的变量 window 时,它实际上链接到我们类中的变量 window 。当调用应用程序更新协议中的变量 window 时,它实际上正在更新我们的变量 window 。因此,当我们需要访问程序中的值时,它已准备就绪并等待。
这是不 Xcode魔术,但是Swift语言不可或缺的一部分。使用协议时,我们可以在自己的Swift程序中使用相同的技术。这与我们一直在做的各种函数的实现相同:例如: UIApplicationDelegate定义
optional public func applicationDidEnterBackground(_ application: UIApplication)
所以我们可以编写自己的实现,然后“神奇地”调用它!
为了完整性,请注意课程上的 @UIApplicationMain 标记。这定义了应用程序的入口点,是使所有内容协同工作的原因。实际的类名是无关紧要的,并且可以给出您需要的任何名称,只要它是UIResponder类型并且符合UIApplicationDelegate。