一、iOS启动过程
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
// 当应用程序启动后将会调用该方法
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
return true
}
//将要进入非活动状态
func applicationWillResignActive(_ application: UIApplication) {}
//程序进入活动状态
func applicationDidEnterBackground(_ application: UIApplication) {}
//程序进入后台
func applicationWillEnterForeground(_ application: UIApplication) {}
//程序从后台将要重新进入前台
func applicationDidBecomeActive(_ application: UIApplication) {}
//内存警告,程序将要终止
func applicationDidReceiveMemoryWarning(_ application: UIApplication){}
//程序将要退出结束
func applicationWillTerminate(_ application: UIApplication) {}
}
说明
1、UIApplicationMain 函数解释
@UIApplicationMain
在C系语言中,程序的入口都是main函数,对于熟悉的OC APP项目,Xcode自动帮我们新建了一个main.m文件,其中就有main函数:
int main(int argc, char * argv[])
{
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
而在swift项目中,没有main.m 文件,也没有 main 函数。而是默认的APPDelegate类的申明上方有个@UIApplicationMain的标签。
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
}
这个标签的作用就是将标注的类作为委托,创建一个 UIApplication 并启动整个程序。一般情况我们不需要对这个标签做任何修改,但如果我们想使用 UIApplication 的子类而不是它本身,我们就要自定义一个 main.swift 文件了(记得删除 @UIApplicationMain 标签)。这个文件我们不需要定义作用域,直接写代码就OK。
import UIKit
class MyApplication: UIApplication {
override func sendEvent(_ event: UIEvent) {
super.sendEvent(event)
print("Event sent:\(event)")
}
}
UIApplicationMain(
CommandLine.argc,
UnsafeMutableRawPointer(CommandLine.unsafeArgv)
.bindMemory(
to: UnsafeMutablePointer<Int8>.self,
capacity: Int(CommandLine.argc)),
NSStringFromClass(MyApplication.self),
NSStringFromClass(AppDelegate.self)
)
int UIApplicationMain(int argc, char *argv[], NSString *principalClassName, NSString *delegateClassName);
- argc和argv:来自于main()函数中接收的两个参数,为了与C语言保持一致,在这没用到,不详述。
- 第三个参数:主要类(principal class),如果不是nil,必须是UIApplication或其子类的名字,如果该参数为nil,那么它的值将从Info.plist中获取,如果Info.plist中没有,则默认为@“UIApplication”。principalClass这个类除了管理整个程序的生命周期之外什么都不做,它只负责监听事件然后交给delegateClass去做。
- 第四个参数:代理类AppDelegate,负责控制程序的运行。NSStringFromClass([AppDelegate class]) //相当于@“AppDelegate”
2、对于applicationWillResignActive(非活动)与applicationDidEnterBackground(后台)这两个的区别。
(1)applicationWillResignActive(非活动):
比如当有电话进来或短信进来,在或者锁屏等,这时你的应用程序挂起进入非活动状态,也就是你的手机其实界面还是显示着你当前的App窗口,只不过被别的任务强制占用了,或者后台状态(因为要先进入非活动状态,然后进入后台)。
(2)applicationDidEnterBackground(后台):
指当前窗口不是你的App,大多数程序进入这个后台后会在在这个状态上停留一会,时间到之后会进入挂起状态(Suspended)。如果你程序特殊处理后可以长期处于后台状态即在后台状态也可以运行。Suspended(挂起):程序在后台不能执行代码。系统会自动把程序变成这个状态而且不会发出通知。当挂起时,程序还是停留在内存中的,当系统内存低时,系统就把挂起的程序清除掉,为前台程序提供更多的内存。
二、Controller和View的生命周期
//加载视图时调用的方法
override func loadview() {
super.loadview()
}
//视图加载完成时调用的方法
override func viewDidLoad()(
super.viewDidLoad ()
}
//将要布局子视图时调用的方法
override func viewwillLayout Subviews ()(
super.viewwillLayout Subviews ()
}
//已经布局子视图时调用的方法
override func viewDidLayout Subviews()
super.viewDidLayout Subviews()
}
//界面将要展现时调用的方法
override func viewwillAppear(_ animated: Bool)[
super.viewWillAppear(animated
}
//界面已经展现时调用的方法
override func viewDidAppear(_ animated: Bool)(
super.viewDidAppear(animated)
}
//界面将要消失时调用的方法
override func viewWillDisappear(_ animated: Bool)(
super.viewwillDisappear(animated
}
//界面已经消失时调用的方法
override func viewDidDisappear(_ animated: Bool)
super.viewDidDisappear(animated)
}
//析构方法
deinit{
}
//收到内存警告时调用的方法
override func didiReceiveMemoryWarning()
super.didiReceiveMemoryWarning()
}
ViewController生命周期中有那么多函数,一个重要问题就是什么代码该写在什么地方。
1. init
init里不要出现创建view的代码。良好的设计,在init里应该只有相关数据的初始化,而且这些数据都是比较关键的数据。init里不要调用self.view,否则会导致viewcontroller创建view。(因为view是lazyinit的)。
2.loadView方法
时view还没有生成,其作用是初始化view,一般用于创建比较关键的view如tableViewController的tabView,UINavigationController的navgationBar,不可掉用view的getter(在调super.loadView前),最好也不要初始化一些非关键的view。如果你是从nib文件中创建的viewController在这里一定要首先调用super的loadView方法,但建议不要重载这个方法。
关于loadView方法的重写,官方文档中有一个明显的注释,意思是:当通过代码方式去创建你自己的view时,在loadView方法中不应该调用super,如果调用[super loadView]会影响CPU性能。
3.viewDidLoad
当VC的view对象载入内存后调用,用于对view进行额外的初始化操作。
4.viewWillAppear
view被添加到superview之前,切换动画之前调用。在这里可以进行一些显示前的处理。比如键盘弹出,一些特殊的过程动画(比如状态条和navigationbar颜色)。
5.viewDidAppear
在view被添加到视图层级中,显示动画切换之后调用(这时view已经添加到supperView中)。在这个方法中执行视图显示相关附件任务,如果重载了这个方法,必须在方法中调用[supper viewDidAppear];
6.viewWillDisappear
view即将从supperView中移除,移除动画切换之后调用,此时已调用removeFromSuperview。
7.viewDidDisappear
view从superView中移除,移除动画切换之后调用,此时已调用removeFromSuperview。这时候viewController的view已经是nil了。
8.viewWillUnload
在VC的view对象从内存中释放之前调用,可以在view被释放前做一些资源清理操作。在ios6.0开始就废弃了,该方法不再会被调用。
9.viewDidUnload
在VC的view对象从内存中释放之后调用,可以在view被释放后做一些view相关的引用清理操作,此时view为nil。在ios6.0开始就废弃了,该方法不再会被调用。
三、UIView生命周期
UIView生命周期相对简单,需从“用XIB加载UIView”和“用代码加载UIView”两方面来说明。
1、用XIB加载UIView
初始化代码:
XibView *xibView = [[[NSBundle mainBundle]loadNibNamed:@"XIBView" owner:self options:nil] lastObject];
[self.view addSubview:xibView];
此时执行的初始化函数顺序为:initWithCoder、awakeFromNib
我的理解:用XIB加载UIView其加载可以放到UIView的initWithFrame函数中,这样对外就可以以“用代码加载UIView”的方式初始化UIView。
2、用代码加载UIView
CodeView *codeView = [[CodeView alloc]init];
codeView.frame = CGRectMake(0, 500, 100, 50);
[self.view addSubview:codeView];
此时执行的初始化函数顺序为:initWithFrame、 init