[转]浅论ViewController的加载 -- 解决 viewDidLoad 被提前加载的问题(pushViewController 前执行)

一个ViewController,一般通过init或initWithNibName来加载。二者没有什么不同,init最终还是要调用initWithNibName方法(除非这个ViewController没有nib文件)。

我们经常在initWithNibName方法中初始化视图,变量或者其他成员。这是最常见的initWithNibName方法写法:

- (id)initWithNibName:(NSString *)nibNameOrNilbundle:(NSBundle *)nibBundleOrNil

{

self = [superinitWithNibName:nibNameOrNil bundle:nibBundleOrNil];

if (self) {

label=[[UILabelalloc]initWithFrame:

CGRectMake(0,0,160,160)];

[self.viewaddSubview:label];

...

}

returnself;

}

在if语句中,包含了最常见的成员初始化代码。

在这段代码中,如果你向ViewController的视图树中加入一些新的UIView子类,比如上面的代码:

[self.viewaddSubview:label];

这不会有什么问题。但是这会导致另一个方法的调用,即viewDidLoad方法。

viewDidLoad方法一般情况下只会在nib文件已载入内存(即视图树构建完成)之后调用。

但还有另一种情况,如果ViewController的view属性被引用时,view=nil,也会导致nib的加载行为,从而也导致viewDidLoad方法的调用。如果你在initWithNibName方法一直不引用view属性,则直至initWithNibName方法结束,viewDidLoad方法也不会触发。

你也许奇怪,如果在代码中你一直不引用这个ViewController的view属性怎么办?那么是不是viewDidLoad方法一直都不会调用了?

它会在ViewController对象第1次present时调用,比如你使用presentModalViewController或pushViewController方法弹出它。这两个方法同时还会调用ViewController的appear方法(即viewWillAppear方法和viewDidAppear方法)。

viewDidLoad方法会比appear方法要早执行(appear方法会导致一个弹出动画产生)。而且如果在present之前已经执行过viewDidLoad方法,则present方法不会触发viewDidLoad方法。

这就是为什么我们会奇怪viewDidLoad方法中的代码有时执行有时似乎不被执行的原因。其实根源还是在initWithNibName方法的if语句中。

如果你在initWithNibName时,引用了ViewController的view属性,由于此时view为nil,将触发nib文件的加载行为,导致viewDidLoad方法不等present就提前调用了。由于initWithNibName方法中ViewController成员还未初始化,导致任何对这些成员的引用都是无效的。

比如在viewDidLoad方法中,由于该方法提前执行,导致数据访问对象还是nil(initWithNibName仍然未执行完)。如果此时在viewDidLoad方法想通过数据访问对象获取表格数据,将得到空。这样从表面上看,viewDidLoad方法似乎未被执行。

这个情况可以通过两种方法来改进:

一、initWithNibName方法中,不要有任何成员初始化的代码。把这些代码移到viewDidLoad方法开始进行。

二、由于initWithNibName方法保证是在present方法中进行,我们也可以在initWithNibName方法中保留成员初始化代码。但把原来viewDidLoad方法中的代码移到appear方法中。也就是,最好不要在viewDidLoad方法中进行和成员初始化无关的事情。这样还有一个好处,每次presentViewController,都会执行appear方法中的代码(如果是viewDidLoad方法,则只会在加载nib时执行)。

loadview也是第1次引用ViewController的view属性(此时,view=nil)时调用,但在viewDidLoad之前。不同的是,loadview在view树构建前调用,viewDidLoad在view树构建完成后调用。二者之间,则进行nib的加载。因此,我们常在编程方式创建viewcontroller时重载loadview方法,因为本来就不需要加载nib的内容。

转:http://blog.sina.com.cn/s/blog_947c4a9f01015i23.html

时间: 2024-08-07 17:55:53

[转]浅论ViewController的加载 -- 解决 viewDidLoad 被提前加载的问题(pushViewController 前执行)的相关文章

浅论ViewController的加载 -- 解决 viewDidLoad 被提前加载的问题(pushViewController 前执行)

一个ViewController,一般通过init或initWithNibName来加载.二者没有什么不同,init最终还是要调用initWithNibName方法(除非这个ViewController没有nib文件). 我们经常在initWithNibName方法中初始化视图,变量或者其他成员.这是最常见的initWithNibName方法写法: - (id)initWithNibName:(NSString *)nibNameOrNilbundle:(NSBundle *)nibBundle

使用Redirector插件解决googleapis公共库加载的问题

最近访问一些面向国外的网站总是会出现ajax.googleaips.com无法加载的情况.以下为加载stackoverflow时的情境: 图1 -无法加载的google公共库 问题的原因是谷歌没有在国内开放ajax公共库服务 使用Redirector解决公共库加载问题 Redirector这个插件的功能正如它的名字, 可以对网页中的内容进行重定向 外部样式表,外部脚本, 图片等均可以添加至作用范围 安装 Redirector目前支持Firefox.Chrome.Opera三款浏览器,可以前往对应

使用live delegate on来解决js对后加载的html失效的问题

今天要写一个前端的东西.每多学一点知识,就可以少写几行代码.几十行代码.几个文件量的代码--这是真的.一直对前端的研究都是停留在遇到问题百度谷歌答案的做法.今天遇到这样一个问题:已经写好的js代码,对ajax加载的html失效了. 用好几组关键字都没有找到答案,最后这组帮我找到了解答的办法: javascript not work on ajax content 很幸运,我来到了:http://stackoverflow.com/questions/10161938/jquery-functio

过滤器解决hibernate中懒加载问题

使用过滤器解决懒加载问题需要我们对过滤器的生命周期有深刻的理解 1.浏览器发送一个请求 2.请求通过过滤器执行dofilter之前的代码 3.浏览器通过过滤器到达Servlet(注意我们这里的servlet指的是Servlet和其他组件比如jsp) 4.请求在servlet中得到处理,并且得到展示(将数据发到jsp中) 5.依次从后往前执行过滤器中的dofilter之后的代码. 6.将数据返回到用户的浏览器上 我们可以通过在过滤器中拿到Session在jsp页面获得数据之后关闭Session 即

Android ListView只加载当前屏幕内的图片(解决list滑动时加载卡顿)

最近在做ListView分页显示,其中包括图片 和文字(先下载解析文字内容,再异步加载图片)发现每次点击下一页后,文字内容加载完毕,马上向下滑动,由于这时后台在用线程池异步下载图片,我每页有20条,也就是20张图片,会导致listview滑动卡顿! 这是用户不想看到的,我参考了网易新闻和电子市场等应用,发现它们都是只加载屏幕内的图片,不现实的不加载,于是我也仿照做了一个.我是菜鸟,我承认 呵呵,虽然不见得完全和他们的一样,但是确实解决了翻页时那一刻的卡顿现象. 因为未发现网上有相关文章,希望对朋

spring加载过程中jar包加载不了,解决方法

当我们在开发spring项目时,一般会将jar包放到webInf/lib下,这样是myeclipse自动将jar包加载到tomcat中webapps下,但是当我们新建一个lib文件夹的情况下,我们add building Path时就会出错,这时候我们有个技巧供使用. 1.项目上点击右键搜索de,找到deployment assembly 目的就是将此处添加的jar包添加到系统webINF/lib路径下 来自为知笔记(Wiz) spring加载过程中jar包加载不了,解决方法

vue-router路由懒加载(解决vue项目首次加载慢)

懒加载:----------------------------------------------------? 也叫延迟加载,即在需要的时候进行加载,随用随载. 为什么需要懒加载? 像vue这种单页面应用,如果没有应用懒加载,运用webpack打包后的文件将会异常的大,造成进入首页时,需要加载的内容过多,时间过长,会出啊先长时间的白屏,即使做了loading也是不利于用户体验,而运用懒加载则可以将页面进行划分,需要的时候加载页面,可以有效的分担首页所承担的加载压力,减少首页加载用时 简单的说

用GCD的方式,加载网络图片(主线程加载图片+类扩展方式)

用GCD的方式,加载网络图片(主线程加载图片+类扩展方式) 用两种方法来实现网络加载图片 方法1:实现的效果:先加载背景色灰色,两秒后加载图片 - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor=[UIColor grayColor]; //刷新UI(在主线程中刷新UI!!!) --- 一般方法 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PR

Swift - 表格图片加载优化(拖动表格时不加载,停止时只加载当前页图片)

列表的单元格中包含有图片在开发中很常见.通常我们可以直接在tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath)中给单元格设置图片. 但有时这些图片要从远程加载,或者要给图片作裁减,添加滤镜等操作.如果这些操作还是直接在主线程中进行,由于上下拖动表格滚动条的时候,单元格渲染是实时进行的.那么单元格便会不断地进行图片加载,渲染,影响效率造成卡顿.如果图片大的话还会浪费流量. 下面通过一个展示“热