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

在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实例化时指定原点。

时间: 2024-08-06 13:13:43

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

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

在开发的过程中难免会遇到很多的错误,可是当看到系统给出的英文时,又不知道是什么意思.所以这篇文章总结了Xcode中常见的一些英文单词及词组,可以帮助初学的人快速了解给出的提示.多练习,就肯定能基本掌握. expression:表达式assignable:赋值variable:变量redefinition:重复定义type:类型conflicting:冲突项invalid:无效的conversion:转换specifier:说明符indent:缩进operands:运算对象.操作数binary:二

java中初始化对象变量的方法

1.在类定义对象的地方初始化 2.在类构造器中初始化 3.在正要使用这些对象之前,惰性初始化,或者叫惰性加载 4.使用实例初始化    在方法里使用初始化 版权声明:本文为博主原创文章,未经博主允许不得转载.

iOS开发OC基础:OC中的分类(类目)

//分类,category,(类目) //为没有源代码的类添加方法 //一定要注意,只能添加方法,不能添加实例变量 /** *  分类 类的定义也是分为接口部分和实现部分 接口部分:以@interface开头 + 类名 后跟小括号,小括号内填写的是分类名 @end结束 在@interface 与@end 之间添加方法. */ //分类为原类添加的方法,就相当于原类具有该方法,可以正常调用 因为涉及到几个分类的创建,所以就直接上传代码了,其实代码也不多,只是怕大家在建立分类的时候会混淆,所以直接把

iOS开发OC基础:OC中的协议

1.协议是一种为有源代码的类扩充方法的方式. 2.协议只是一系列方法的生命,就相当于一张任务清单,规定了要做的事情,但是具有的实施(也就是实现),是由服从该协议的类来实现.所以协议只有.h文件,并且不可以定义变量 3.协议的定义是以@protocol开头, + 协议的名字 <>(表示服从的协议)服从的协议写在<>之内,多个协议之间通过逗号来进行分隔,父协议中的内容就相当于子协议也具有这些内容,以@end结束. 下面的附件是协议的一个小例子,可以加深大家对协议的理解,看完之后一定要多

iOS Dev (60) 怎样实现 UITextView 中的 placeHolder

iOS Dev (60) 怎样实现 UITextView 中的 placeHolder 作者:阿锐 地址:http://blog.csdn.net/prevention - 跟着你的 UITextView 定义一个 UILabel. UILabel *inputPlaceHolder; placeHolder 是当有内容时不显示.无内容时显示.所以能够为所在的实例相应的类实现 UITextViewDelegate 中例如以下方法. - (void)textViewDidChange:(UITex

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

ios开发UI篇—在ImageView中添加按钮以及Tag的参数说明 一.tag参数 一个视图通常都只有一个父视图,多个子视图,在开发中可以通过使用子视图的tag来取出对应的子视图.方法为Viewwithtag: 提示点:在xib中如果想要通过tag参数获取对应的控件(属性),不要把tag的参数设置为0,因为xib中所有的对象默认tag都为0,设置为0取不到对象. 二.ImageView中添加按钮(1)ImageView和Button的比较 Button按钮的内部可以放置多张图片(4),而Ima

GCC中初始化函数是如何被处理的?

本文译至: http://gcc.gnu.org/onlinedocs/gccint/Initialization.html 如我们所知,在GCC通过给代码追加__attribute__((constructor))和__attribute__((destructor))的方式可以追加初始函数和终止函数, 这篇文章介绍了GCC内部是如何实现上述处理的. 简单的说,就是在最经常的情况下,初始函数会被追加到.ctor section中,.init会调用对应的函数处理这些初始函数.终止情况类似. --

Cocos2d-x 3.1.1 学习日志2--error:只有静态常量整型数据成员才可以在类中初始化

今天遇到比较低端的一个问题,就是成员的初始化问题,编译器也无法验证,不同的编译器有些能过有些不能过,我也不知道为什么,总是我们以vs为准吧,以为我们用的环境就是它,话不多说,解决方案如下: 在类中    static const double PI=3.1416; error:只有静态常量整型数据成员才可以在类中初始化 常整型静态数据成员可以在类中直接初始化,而常实型静态数据成员不可以 class circle { int a; // 普通变量,不能在类中初始化 static int b; //

IOS开发UI基础—在UIImageView中添加按钮以及Tag的参数说明

ios开发UI基础-在ImageView中添加按钮以及Tag的参数说明 一.tag参数 一个视图通常都只有一个父视图,多个子视图,在开发中可以通过使用子视图的tag来取出对应的子视图.方法为Viewwithtag: 提示点:在xib中如果想要通过tag参数获取对应的控件(属性),不要把tag的参数设置为0,因为xib中所有的对象默认tag都为0,设置为0取不到对象. 二.ImageView中添加按钮(1)ImageView和Button的比较 Button按钮的内部可以放置多张图片(4),而Im