AppDelegate,RootViewController和UIApplication之间的关系是什么?

问题描述:

我想弄清楚appdelegate,RootViewControoler和UIApplication之间的关系。以下是我到目前为止已经计算出来的结果:AppDelegate,RootViewController和UIApplication之间的关系是什么?

当启动应用程序时,main.m被加载。

从这里,你的MainWindow.xib被加载。

在您的MainWindow.xib中,您的文件所有者是UIApplication类型的。

您将您的UIApplication委托给您的AppDelegate。

在您的AppDelegate的源代码中,您可以将RootViewController设置为显示的第一个视图。

这是正确的吗?什么提示AppDelegate最初运行它的

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { } 

方法?

+1

这是正确的!,“didFinishLaunchingWithOptions”是第一个执行的方法! – 2011-02-10 06:25:28

当Objective-C应用程序启动时,它通过运行名为main()的函数来启动。它不必在文件“main.m”中,但这是Xcode向导如何设置的。

里面的向导生成main()函数,有这样一行:

int retVal = UIApplicationMain(argc, argv, nil, nil); 

这就是启动“的UIKit”框架,构成了整个应用程序。在UIApplicationMain里面,创建一个UIApplication类型的对象。 UIApplication在应用程序启动时执行的部分工作是在UIApplication类的委托成员上调用applicationDidFinishLaunchingWithOptions方法。此代理在MainWindow.xib文件中设置为您的ProjectAppDelegate类的一个实例,它是NSObject的一个符合UIApplicationDelegate协议的子类。

是什么促使AppDelegate中最初 来看,这是......

因为你的MainWindow.xib文件中已连接(以及项目向导做了连接实际上)文件的所有者(这是UIApplication对象)的“委托”出口指向.xib文件中的UIApplicationDelegate对象,并且将UIApplicationDelegate的类设置为应用程序的UIApplicationDelegate子类。

“MainWindow.xib”没有什么魔力,它可以被称为“Foo.xib”,重要的是Info.plist文件中名为“Main nib file base name”的属性是“MainWindow”。尝试将MainWindow.xib重命名为Foo.xib,并将Info.plist中的“Main nib文件基本名称”更改为“Foo”,然后您会看到它仍然有效。

编辑:更多关于RootController

再次,没有什么神奇的关于所谓“RootController”。这只是Xcode新项目向导为您创建的UIViewController子类的名称。

该向导将项目中的代码放置在两个类中:ProjectAppDelegate和ProjectViewController。所述ProjectAppDelegate类包含两个引出件:

IBOutlet UIWindow *window; 
IBOutlet ProjectViewController *viewController; 
在的MainWindow.xib文件

,既一个UIWindow和ProjectViewController的实例被放置,并接通了在ProjectAppDelegate上述网点。

什么得到你的东西在屏幕上是这样的代码在你的ProjectAppDelegate类:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {  

    // Override point for customization after application launch. 

    // Add the view controller's view to the window and display. 
    [self.window addSubview:viewController.view]; 
    [self.window makeKeyAndVisible]; 

    return YES; 
} 

同样,没有什么神奇的这个问题:项目向导创建的代码,增加了你的“根”视图控制器的观点的窗口的视图,并使窗口可见。您的“根”视图控制器是在.xib文件中创建的,并且连接到ProjectAppDelegate插座。

尝试完全由自己创建应用程序而不使用向导中的任何文件是非常有益的。您将学习很多关于.xib文件如何工作以及它们如何与代码对象关联的知识。

+0

刚刚提出这个,所以我可以看到你从9997到10k:p。答案也不错。 – 2013-08-12 21:04:41

+0

w00t :)很酷,谢谢 – Bogatyr 2013-08-12 21:38:57

MainWindow.xib在您的info.plist中定义为Main nib file base name。在你的MainWindow.xib中,你定义了你想要加载的第一个控制器,在你的情况下,RootViewController

didFinishLaunchingWithOptions:UIApplicationDelegate协议的一部分。这种方法(在iOS4.0 +中)总是被称为在启动应用程序时首先被调用。

由于您的AppDelegate是UIApplication的代表,因此它会监听UIApplication类在其生命周期中发布的所有通知。 didFinishLaunching通知是其中的一个,它会导致您的AppDelegate调用上述方法。

+5

那么,代表并不真正“听”通知(就像注册为NSNotificationCenter的观察者一样)。相反,UIApplication会查看delegate是否使用`respondsToSelector:`实现了各种方法,并在它们存在时调用它们(它需要具有完全预定义的名称,而不是侦听可以自己命名目标选择器的通知)。 – DarkDust 2011-02-10 07:03:05

iOS应用的出发点始终是main()功能(感谢@bogatyr)通常含有类似的代码,

int main(int argc, char *argv[]) { 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 
    int retVal = UIApplicationMain(argc, argv, nil, nil); 
    [pool release]; 
    return retVal; 
} 

UIApplicationMain最后两个参数是很重要的,并指定主类名,应用程序委托。如果它们是nil,那么将查找Info.plist以查找主窗口xib(通常为MainWindow.xib)。

// If nil is specified for principalClassName, the value for NSPrincipalClass 
// from the Info.plist is used. If there is no NSPrincipalClass key specified, the 
// UIApplication class is used. The delegate class will be instantiated 
// using init. 
.. UIApplicationMain(int argc, char *argv[], NSString *principalClassName, NSString *delegateClassName); 

这是没有必要通过厦门国际银行设置文件所有者,他们可以直接在此UIApplicationMain功能来指定。

principalClassName可以是字符串UIApplicationUIApplication的子类。同样可以用这种方法直接指定delegateClassName。如文档所述,委托类使用init实例化。假设我们指定委托类 - MyAppDelegate作为一个字符串,

UIApplicationMain(int argc, char *argv[], nil, @"MyAppDelegate"); 

第一的UIApplication的实例的实例,然后将使用NSClassFromString我想这个字符串创建委托类。

一旦delegateObject已被实例化,并且应用程序已准备就绪,则将使用委托方法通知此delegateObject。

Class delegateClass = NSClassFromString(@"MyAppDelegate"); 
id <UIApplicationDelegate> delegateObject = [[delegateClass alloc] init]; 

// load whatever else is needed, then launch the app 
// once everything is done, call the delegate object to 
// notify app is launched 
[delegateObject application:self didFinishLaunchingWithOptions:...]; 

这是UIApplication如何使用编程方式处理它,如果没有使用nib的话。在中间使用笔尖没什么不同。

通用 - iPhone + iPad的 - 应用程序,您可以指定每个平台上,不同的发钞银行的负载,无论是在目标信息面板或者通过添加NSMainNibFile~ipadNSMainNibFile~iphone钥匙给您Info.plist。或者,您可以添加一个MainWindow~ipad.xib NIB到您的目标,它将基于Info.plist中的NSMainNibFile密钥在iPad上加载而不是MainWindow.xib加载。

如果您需要对通用应用程序进行更多控制和自定义,则可以手动加载开始的NIB。 “通用”项目模板具有此方法的样板,因此开始使用此技术的最快方法是使用通用配置文件创建一个新的iOS项目。

在上面的示例中,Main NIB File设置为Info.plist(目标设置),以便您在调用应用程序委托时已经加载了NIB。通常在此设置中,MyAppDelegate对象也将存档在NIB中(部分IBOutlets),而NIB的File's Owner将设置为UIApplication

对于通用的项目,以便能够容纳两个备选的布局,主NIB文件键冷落Info.plist。然后编程实例应用程序委托对象UIApplicationMain

#import "MYAppDelegate.h" 

int main(int argc, char *argv[]) 
{ 
    @autoreleasepool { 
    return UIApplicationMain(argc, argv, nil, NSStringFromClass([MYAppDelegate class])); 
    } 
} 

然后检查你的环境和设置并加载相应的NIB在application:DidFinishLaunchingWithOptions:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
    _window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; 
    // Override point for customization after application launch. 
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { 
    _viewController = [[[MYViewController alloc] initWithNibName:@"MYViewController_iPhone" bundle:nil] autorelease]; 
    } else { 
    _viewController = [[[MYViewController alloc] initWithNibName:@"MYViewController_iPad" bundle:nil] autorelease]; 
    } 
    _window.rootViewController = _viewController; 
    [_window makeKeyAndVisible]; 
    return YES; 
} 

- (void)dealloc { 
    [_window release]; 
    [_viewController release]; 
    [super dealloc]; 
} 

的新的一步是手动创建一个根MYViewController,装载适当的NIB。在这个设置中,File's Owner是您闪亮的新MYViewController而不是UIApplication。如果你愿意,MYViewController可以采用你可能已经使用你的应用程序委托的大部分内容 - 这通常是封装应用程序的核心模型类,充当数据源并委托NIB中的视图和其他事物。

所以你希望有一定的根UIView在NIB,并应挂在view出口File's OwnerMYViewController)的。

注意MYViewController的NIB没有实际加载的第一次MYViewController.view属性进行访问,直到。只有这样才会调用[MyViewController viewDidLoad]!发生这种情况的最可能时间是将其添加到根窗口时。

在上面显示的模板代码中,根目录UIWindow由应用程序委托实例化,但没有理由不能将其包含在您的NIB中。如果你选择这样做,小心点。如果在这种情况下将NIB中的窗口的rootViewController设置为文件所有者,则会在窗口被激活时将控制器的视图添加到窗口中。无论如何,请小心构建第一个NIB。

如果您希望MYViewController管理它,应用程序委托并不一定需要对您的根UIWindow进行引用,但总体而言,它可以使根窗口保持在您的NIB之外,并在应用程序委托中对其进行管理。

除此之外(!)与单平台方法没有多大区别。