UIApplicationDelegate
每个 iOS 应用程序都有一个 UIApplication
,UIApplication
是 iOS 应用程序的开始并且负责初始化并显示 UIWindow,并负责加载应用程序的第一个 UIView 到 UIWindow 窗体中。
UIApplication
的另一个任务是帮助管理应用程序的生命周期,而 UIApplication
通过一个名字为 UIApplicationDelegate
的代理类来履行这个任务。尽管 UIApplication
会负责接收事件,而 UIApplicationDelegate
则决定应用程序如何去响应这些事件,UIApplicationDelegate
可以处理的事件包括应用程序的生命周期事件(比如程序启动和关闭)、系统事件(比如来电、记事项警 告)。
通常是没必要修改UIApplication的,只需要知道 UIApplication 接收系统事件即可。处理系统事件需要编写一个继承自 UIApplicationDelegate 接口的类,而 UIApplicationDelegate 接口提供生命周期函数来处理应用程序以及应用程序的系统事件。我们新建项目的时候,往往会自动生成一个继承自 UIApplicationDelegate 接口的类AppDelegate。
UIApplicationDeleagte 的生命周期
#pragma mark 在应用程序加载完毕之后调用
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSLog(@"didFinishLaunchingWithOptions-加载完毕");
// 初始化一个窗口
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// 传入xib文件名来初始化一个控制器
self.viewController = [[[TestViewController alloc] initWithNibName:@"MJViewController" bundle:nil] autorelease];
// 设置窗口的根控制器
self.window.rootViewController = self.viewController;
// 上面的代码内部执行了下面代码的操作
// [self.window addSubview:self.viewController.view];
// 窗口不会默认显示,需要调用方法来显示
// keyWindow是主窗口,只有主窗口才能跟用户正常交互
[self.window makeKeyAndVisible];
// self.window.hidden = NO;
return YES;
}
#pragma mark 程序不活跃状态的时候调用(不能跟用户进行交互了)
- (void)applicationWillResignActive:(UIApplication *)application
{
NSLog(@"applicationWillResignActive-不活跃状态");
}
#pragma mark 当应用程序进入后台的时候调用(点击HOME键)
- (void)applicationDidEnterBackground:(UIApplication *)application
{
NSLog(@"applicationDidEnterBackground-进入后台");
}
#pragma mark 当应用程序进入前台的时候调用
- (void)applicationWillEnterForeground:(UIApplication *)application
{
NSLog(@"applicationWillEnterForeground-进入前台");
}
#pragma mark 当应用程序处于活跃状态的时候调用
// 处于不活跃状态之后才可以跟用户进行交互
- (void)applicationDidBecomeActive:(UIApplication *)application
{
NSLog(@"applicationDidBecomeActive-活跃状态");
}
#pragma mark 程序在某些情况下被终结时会调用这个方法
- (void)applicationWillTerminate:(UIApplication *)application
{
NSLog(@"applicationWillTerminate-被关闭");
}
下面输出:
程序启动后:
didFinishLaunchingWithOptions -- 加载完毕
applicationDidBecomeActive -- 处于活跃状态
按下home键:
applicationWillResignActive -- 处于不活跃状态
applicationDidEnterBackground -- 进入后台
再按程序:
applicationWillEnterForeground -- 进入前台
applicationDidBecomeActive -- 处于活跃状态
UIViewController
UIViewController
是负责内部的各个 UIView
加载显示和移除卸载,下面是 UIView的加载过程
从图中可以看到,在 view 加载过程中首先会调用 loadView
方法,在这个方法中主要完成一些关键view的初始化工作,比如UINavigationViewController
和 UITabBarController
等容器类的 ViewController;
接下来就是加载view,加载成功后,会接着调用 viewDidLoad
方法,这里要记住的一点是,在 loadView
之前,是没有view的,也就是说,在这之前,view还没有被初始化。完成 viewDidLoad
方法后,ViewController里面就成功的加载view了,如上图右下角所示。
在Controller中创建view有两种方式,一种是通过代码创建、一种是通过 Storyboard
或 Interface Builder
来创建,后者可以比较直观的配置view的外观和属性,Storyboard
配合IOS6后推出的 AutoLayout
,应该是Apple之后主推的一种UI定制解决方案。
UIView 卸载过程:
UIViewController-UIviewUnload.png从图中可以看到,当系统发出内存警告时,会调用 didReceiveMemoeryWarning
方法,如果当前有能被释放的view,系统会调用viewWillUnload方法来释放view,完成后调用 viewDidUnload
方法,至此,view就被卸载了。此时原本指向view的变量要被置为nil,具体操作是在 viewDidUnload
方法中调用 self.myView = nil
;
UIViewController 生命周期
ViewController的生命周期中各方法执行流程如下图:
UIViewCroller-LifeCycle.png各个方法调用流程:
@interface ViewController ()
@end
@implementation ViewController
- (instancetype)init
{
self = [super init];
if (self) {
NSLog(@"ViewController 初始化");
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
NSLog(@"ViewController 从归档初始化");
}
return self;
}
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.view.backgroundColor = [UIColor whiteColor];
NSLog(@"ViewController 从xib初始化");
}
return self;
}
- (void)loadView {
[super loadView];
NSLog(@"ViewController 开始加载视图");
}
- (void)loadViewIfNeeded
/**
这个方法用的时候,outlet还没有连接起来,是view Controller刚从storyboard建的时候,没有完全建好
不过可能有一些事情要在这个方法里面完成,比如splitViewDelegate,需要在非常早期完成。
*/
- (void)awakeFromNib{
[super awakeFromNib];
NSLog(@"ViewController awakeFromNib");
}
/**
用这个的时候,ViewController已经完全好了,outlet也已经连接好了。但是还没有在屏幕上显示出来。
这个方法里面可以放很多设置的代码。
这个方法执行的时候,view的bounds还没有。先load,再appear嘛。
*/
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"ViewController 已经加载视图");
}
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
NSLog(@"ViewController 开始布局子视图");
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
NSLog(@"ViewController 完成布局子视图");
}
/**
这个方法调用的时候,bounds已经有了。
你的视图只会loaded一次,但是会appear或者disappear很多次。所以不变的东西,放在viewDidLoad里面。和几何相关的,放在viewWillAppear里面。这点对项目的优化很重要的
就好似顶层的view,旋转ipad什么的都需要改变顶层的view的大小,当一个view controller的生命周期到这里的时候,就可以在这里的最后时刻来调整view的排列或者几何特性。
这里也设置做一些lazy execution for performance.比如:需要按一个button,出现一个view什么的。
这里设置,开销很大。耗时很长的事情最好在viewWillAppear里另开一个线程运行,然后在view里面放一个小小的spinning wheel。
*/
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSLog(@"ViewController 即将显示");
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSLog(@"ViewController 已经显示");
}
/**
这个方法当然是要消失的时候啦。要消失的时候,还是记得现在的运行情况的。所以可以记得scroll的position啦。
但是,不要在这个方法里面写太多的东西哦,app会崩溃的。
*/
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
NSLog(@"ViewController 即将消失");
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
NSLog(@"ViewController 已经消失");
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
NSLog(@"ViewController 收到内存警告");
}
@end
网友评论