alloc
创建控制器,分配内存地址
init
初始化控制器。
loadView
加载视图。控制器被创建以后,其view并没有随之创建(即self.view是为nil),而是在该方法中创建view,将其赋值给self.view。若是nib文件,则加载nib中的view(包括子视图);若是纯代码,则自动创建一个view。
viewDidLoad
视图加载完毕。可以在这里对视图做自定义的更改。需要注意的是在该方法中视图(self.view)还没有进行屏幕适配,也就是说,如果是从nib中加载的,nib中的view多大,self.view.frame就多大;如果是纯代码加载的控制器,frame默认是(320,568)。因此在这个方法中自定义视图如果要借助view.frame就要格外小心了。
viewWillAppear
视图即将显示到屏幕。view会在这里去适应屏幕的大小,因此view
.frame会更新。frame更新会调用view的layoutSubViews方法,在调用会触发控制器的viewWillLayoutSubviews方法,调用完毕后触发viewDidLayoutSubviews,这两个方法不把它们当成生命周期函数看待,因为其驱动因素是layoutSubViews方法。
viewDidAppear
视图显示到屏幕上。此时控制器的视图已经适配了屏幕,并且子视图都布局完毕。
viewWillDisappear
视图即将消失
viewDidDisappear
视图从屏幕上消失
执行main函数,main函数内部执行UIApplicationMain方法,下面都是该方法做的事:
加载info.plist文件,读取Main storyboard file base name字段的值,若值不为空,则从storyboard中加载控制器,执行5;否则执行6。
如下
通 AppDelegate启动app,调用启动方法didFinishLaunchingWithOptions。由于系统并没有创建AppDelegate的UIWindow对象,因此需要在启动方法中自行创建,并配置好rootViewController,最后手动显示window。
当不显示导航栏或者显示的导航栏为半透明时,view坐标原点在屏幕左上角,这种情况下view最终的高度为屏幕高度;当显示的导航栏不透明时,view的坐标原点在导航栏左下角,这时view最终的高度为屏幕高度-64(之所以说最终是因为view在即将显示时才去适配屏幕大小,再此之前加载的view为多大frame即为多大)。
因此为了避免在有不透明导航栏的情况下self.view.frame.height为屏幕高度减64的特例,通常做法是在viewDidLoad异步执行一个方法,在该方法中代替viewDidLoad做自定义视图等相关操作。
dispatch_async(dispatch_get_main_queue(), ^{
[self initBaseView];
});
由于异步执行, [self initBaseView] 会等到主队列中的生命周期函数(一直到viewDidAppear)执行完毕才执行,这时候获取到的self.view.frame.height就是能够操作的高度,即在无导航栏或者有透明导航栏时,高度为屏幕高度;有不透明导航栏时,高度为屏幕高度-64。
状态栏 导航栏
状态栏高度为20,导航栏高度为44。在没有导航栏的情况下,状态栏背景颜色为透明色。当有导航栏的情况下,状态栏背景颜色和导航栏一致(通过barTintColor属性设置)。
状态栏、导航栏并不是当前控制器的view的一部分!状态栏由APP维护,导航栏则是导航控制器的一部分。
问题上下文如下:
一个导航栏下面紧跟着一个搜索栏,点击搜索框输入内容时,动态隐藏导航栏,搜索栏跟着上移,但是并不是移到屏幕顶端,而是距屏幕顶端20高度处。原因是什么?要怎么做才能移动到屏幕顶端?
原因在于自动布局的时候搜索栏的topSpace是根据Top Layout Guide设置的,并不是根据view设置的。如下图:
导航栏隐藏之前Top Layout Guide为导航栏的bottom,当导航栏隐藏之后,虽然导航栏frame从 {{0, 20}, {414, 44}} 变为 {{0, -44}, {414, 44}} ,但是搜索框的topSpace所依据的Top Layout Guide却变为状态栏的bottom,因此搜索栏未能跟随导航栏移动到屏幕顶端。
解决办法是将topSpace约束相对于view设置即可。即设置的时候选择上图中的View。在导航栏隐藏之前,View的坐标原点位于导航栏左下角(假设导航栏为非透明的),当导航栏隐藏之后,View的左边原点变为屏幕左上角,因此searchBar会跟着上移到屏幕顶端
今天在捣鼓UI时遇到了UITableView显示内容比预想位置低了不少情况,感觉很莫名其妙。后来google了一下,发现是automaticallyAdjustsScrollViewInsets这个属性在搞鬼。automaticallyAdjustsScrollViewInsets是iOS7出的试图控制器的属性,官方说明如下:
The default value of this property is YES, which lets container view controllers know that they should adjust the scroll view insets of this view controller’s view to account for screen areas consumed by a status bar, search bar, navigation bar, toolbar, or tab bar. Set this property to NO if your view controller implementation manages its own scroll view inset adjustments.
听起来比较抽象,简而言之就是将该属性设置为YES之后,视图控制器就会自动调整其view中的scrollView控件的contentInset,具体怎么调整,一头雾水!
于是我在工程中把视图控制器的该属性设置为NO,问题确实解决了。不过似乎这个属性的“自动调整”反而给我帮了倒忙了!另外发现网上好多人多这个属性几乎没什么用处,唯一有用的环境如下:
在一个视图控制器中全屏添加一个UITableView(UIScrollView),假如当前导航栏是半透明的,细心的同学会发现,UITableView在显示时顶部是贴着导航栏下沿的,而预想应当是紧贴屏幕顶端才是(edgesForExtendedLayout属性为默认的UIRectEdgeAll)。事实上,UITableView确实是贴着屏幕顶端的,我们看上去贴着导航栏下沿,只是因为控制器自动对UITableView的contentInset做了调整,打印查看是(64,0,0,0),这就解释得通了。这完全是automaticallyAdjustsScrollViewInsets的功劳,默认设置为YES。
不过话说回来,只是少写了一条手动设置contentInset的代码…因此如果编码过程中出现莫名其妙的UIScrollView显示位置异常,很可能就是这个属性在作祟!个人认为这个属性还是比较奇葩的。