在XCode 4.2后,我基本上的应用都不使用Xib文件了,虽然xib文件有很多好趣,可以快速免代码构建视窗,可以减少好多代码构建带来的麻烦,其实能用xib还是不错的,主要是我的机器打开xib来编辑时太慢了,跑不动了,老古董 的机器了,所以不怎么喜欢xib了(个人原因)。有人说xib会让代码跑起来效率慢,真的是这样吗?从理论上来看,APP要运行,先读INFO.PLIST文件,然后找到MAINWINDOW 的XIB,然后解释XIB中的代码来演变成OC代码进行实例化。而用普通代码构建,直接使用代码CODE而不用翻译XIB中的数据,省了一个步骤,或许就是这相原因吧。好了,这个先别讨论了,回到loadView,每一个VC(ViewController)都会生成一个loadview方法,当然,很多情况下都不怎么在这个方法中来写视窗,而是在ViewDidLoad中来写。先看看loadView调用的触发条件吧。

APP 运行,先跑init 然后跑

 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 来查找XIB中有没有视图view。如果有,则不会再走loadView。如果这个时候你的VC是没有xib的,哪么显然走这个方法后,是找不到任何view的,即self.view 仍为nil.然后,就跑loadview,这个时候会被触发,如果在loadView中,什么也不做,也不实例化一个View。哪么程序继续跑到viewDidLoad里,如果这里还是没有实例化VIEW。哪么这个VC就没有视窗。在这里很多时侯会出现一个误区 (死循环)。
 
 
好,下面来解释一下死循环的条件。
 
1、没有XIB。
2、ViewController中的loadView方法中没有做任何实例化self.view的操作。如:
-(void)loadView
{
写了一大堆代码,但最好并没有执行以下两种方式中的其中一种。
//方式一:实例化时使用[supper loadView];    
               //方式二 : self.view = [UIView alloc]....       
}
3、在viewDidLoad中调用了self.view。
 
只要这三个条件同时满足,必定死循环。方式一时,调用了[Supper LoadView] 这个时候由父类产生了一个(0,20,Width,height )。这里的宽高根据是IPAD,还是IPHONE不同而不同,但原点坐标一定是(0,20)即去除状态条。方式二,没有对self.view作任可赋值,所以使得self.View = nil;
在条件二满足的情况下,程序运行到步骤三,这个时候,如果在这里调用了self.View。因为self.View在步骤二中为空,所以又回调到了loadView来,但因loadView中没有对self.View作实例化,于是在跑完loadView后,又继续跑viewDidLoad,但因ViewDidLoad中又没有实例化的情况下,使用了self.View.因此就出会现来回调用的现象。
 
好了,知疲知已方能百战百胜。解决死循环。
 
在步骤二中下手,处理方式有三:
a、把整个-(void)loadView 屏蔽掉。让父类自己来创建一个VIEW。这个是最常见的,因为ViewController产生的时候默认代码中是把这段代码给注释了的。
b、在loadView中添加一句[Supper LoadView];个人不太建议这样写吧,当然如果你理解了VIEW之间的关系,也无所谓。
c、在loadView中,使用已实例化的View对Self.View进行赋值。注:是使用=号赋值,而不是使用[self.view addSubView]因为此时self.view 是空指针,执行ADD操作会崩溃的。
 
另外,也可以在步骤三中下手,即使在步骤二中没有任何实例化VIEW操作,但在步骤三中进行了相应的实例化操作,仍可以解决的。这就是通常我们为什么不打开-loadView的注释,而直接在ViewDidLoad中进行添加视窗。
 
 好了,上面的死循环介绍完了,顺便对使用下面两个方法来实例化视窗注意的地方。
 1、[[UIScreen mainScreen] bounds]    返回的Rect是以(0,0)为坐标原点的大小,即包括了状态栏。 
2、[[UIScreen mainScreen]applicationFrame] 返回的Rect是(0,20)为坐标点的大小,不包括状态栏。通常使用[supper loadView]所产生的的VIEW也就是这个所产生的。
 
如果在loadView中,调用[supper loadview];或使用self.view =[[ [UIView alloc]initWithFrame:[[UIScreen mainScreen]applicationFrame] ]autorelease]; 这样在父子层之间使用AddSubView,你会看到一个偏移量为20的层叠视窗。原因就是这两个方式返回的RECT的原点都是(0,20);
DEMO:
A  Viewcontroller
中的
 - (void)loadView 

    [super loadView]; 
    //self.view  = [[[UIView alloc] initWithFrame:[[UIScreen mainScreen]applicationFrame]] autorelease]; 
     
    //self.view  = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 200, 400)];  
                    
    self.view.backgroundColor = [UIColor greenColor]; 
    
    BVC *bvc = [[BVC alloc]init]; 
    NSLog(@"bvc View %@",bvc.view); 
    [self.view addSubview:bvc.view];

}

B ViewController 中的
 - (void)loadView 

    
    [super loadView]; 
    //self.view  = [[[UIView alloc] initWithFrame:[[UIScreen mainScreen]applicationFrame]] autorelease]; 
    //self.view  = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 200, 400)];  
     
    self.view.backgroundColor = [UIColor redColor]; 
     
    CVC *cvc = [[CVC alloc]init]; 
    [self.view addSubview:cvc.view]; 
     
c ViewController中的
 - (void)loadView 

    [super loadView]; 
    //self.view  = [[[UIView alloc] initWithFrame:[[UIScreen mainScreen]applicationFrame]] autorelease]; 
    //self.view  = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 100, 300)];  
  
    self.view.backgroundColor = [UIColor blueColor]; 
最后运行效果:
 
如果想子视图直接复盖父视图的大小可以使用[[UIScreen mainScreen] bounds]或者直接用UIVIEW实例化时指定原点。
就这样吧,希望这些对你有帮助。

IOS 的loadView 及使用loadView中初始化View注意的问题。(死循环并不可怕)的更多相关文章

  1. Android 和iOS 中关于View 的一点知识

    View的概念和方法十分重要,这里将对Android 和iOS中出现的,关于视图的一些知识点进行总结,预计文章会比较长,要许多时间慢慢补充. 先转载一部分资料,感谢原作者! 原链接为:http://b ...

  2. iOS开发OC基础:Xcode中常见英文总结,OC常见英文错误

    在开发的过程中难免会遇到很多的错误,可是当看到系统给出的英文时,又不知道是什么意思.所以这篇文章总结了Xcode中常见的一些英文单词及词组,可以帮助初学的人快速了解给出的提示.多练习,就肯定能基本掌握 ...

  3. IOS 开发中 Whose view is not in the window hierarchy 错误的解决办法

    在 IOS 开发当中经常碰到 whose view is not in the window hierarchy 的错误,该错误简单的说,是由于 "ViewController" ...

  4. ZeroMQ接口函数之 :zmq_msg_init_data - 从一个指定的存储空间中初始化一个ZMQ消息对象的数据

    ZeroMQ 官方地址 :http://api.zeromq.org/4-1:zmq_msg_init_data zmq_msg_init_data(3) ØMQ Manual - ØMQ/3.2.5 ...

  5. iOS图片加载到内存中占用内存情况

    我的测试结果: 图片占用内存   图片尺寸           .png文件大小 1MB              512*512          316KB 4MB              10 ...

  6. iOS应用架构谈(二):View层的组织和调用方案(中)

    iOS客户端应用架构看似简单,但实际上要考虑的事情不少.本文作者将以系列文章的形式来回答iOS应用架构中的种种问题,本文是其中的第二篇,主要讲View层的组织和调用方案.中篇主要讨论MVC.MVCS. ...

  7. iOS开发UI篇—在UIImageView中添加按钮以及Tag的参数说明

    ios开发UI篇—在ImageView中添加按钮以及Tag的参数说明 一.tag参数 一个视图通常都只有一个父视图,多个子视图,在开发中可以通过使用子视图的tag来取出对应的子视图.方法为Viewwi ...

  8. iOS开发UI篇—iPad开发中得modal介绍

    iOS开发UI篇—iPad开发中得modal介绍 一.简单介绍 说明1: 在iPhone开发中,Modal是一种常见的切换控制器的方式 默认是从屏幕底部往上弹出,直到完全盖住后面的内容为止 说明2: ...

  9. dotNet中初始化器的使用

    dotNet中初始化器的使用 2013年12月7日 13:27 有两类初始化器: 对象初始化器和集合初始化器 比如现在有一个User类: Public   class User { public in ...

随机推荐

  1. [shell基础]——cut命令

    cut命令常见选项

  2. mysql启动问题access denied for user 'root'@'localhost'(using password:YES)

    安装Mysql后利用SQLyogEnt启动是提示“access denied for user 'root'@'localhost'(using password:YES)”,开始我还为是因为是密码问 ...

  3. javascript各种模式解析

    1.工厂模式: 工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程(后面还将讨论其他设计模式及其在JavaScript 中的实现).考虑到在ECMAScript 中无法创建 ...

  4. 搭建SpringMVC+MyBatis开发框架六

    建立Springmvc包结构 1.看看我们在springmvc.xml中曾经配置过扫描net.quickcodes这个包下面的所有java文件:  现在我们就在"src/main/java ...

  5. [转载]关于android SDK安装Failed to fetch URL http://dl-ssl.google.com/android/repository/addons_list-1.xml出错

    原文地址为:http://blog.csdn.net/springsky_/article/details/7442388 因为入行移动测试,所以很多测试环境的搭建.从中遇到了和这个GG同样的问题.怕 ...

  6. Applicationpoolidentity 好有趣哦

    前言: 在服务器上搭建一个网站 Windows Server2008 R2 +IIS7. 应用程序池默认选择ApplicationPoolIdentity.为了适应分布式需求,所以将SqlServer ...

  7. bzoj 1800 暴力枚举

    直接暴力枚举四个点,然后判断是否能组成矩形就行了 注意枚举的点的标号从小到大,保证不重复枚举 /**************************************************** ...

  8. 求字符串的最长回文字串 O(n)

    昨天参加了某公司的校园招聘的笔试题,做得惨不忍睹,其中就有这么一道算法设计题:求一个字符串的最长回文字串.我在ACM校队选拔赛上遇到过这道题,当时用的后缀数组AC的,但是模板忘了没写出代码来. 回头我 ...

  9. Leetcode#151 Reverse Words in a String

    原题地址 将单词按空格分词,然后倒序拼接即可 代码: void reverseWords(string &s) { vector<string> words; ; ; ; i &l ...

  10. AutoResetEvent 运用

    static AutoResetEvent are = new AutoResetEvent(true);//初始化为开 static void Main(string[] args) { //如果这 ...