您的位置:首页 > 移动开发 > IOS开发

iOS Nib文件与手动编码初始化区别

2016-09-23 17:46 309 查看
从Nib中加载对象实例时,init:或initWithFrame:都不会调用。而是调用initWithNibName
或initWithCoder:怎么理解?
1. initWithFrame方法是什么?
initWithFrame方法用来初始化并返回一个新的视图对象,根据指定的CGRect(尺寸)。
当然,其他UI对象,也有initWithFrame方法。我们可以以UIView为例,来搞清楚initWithFrame方法。

2.什么时候用initWithFrame方法?
简单的说,我们用手动编码方式声明、创建UIView对象时,会使用initWithFrame方法。

3.在此,我们必须搞清楚,初始化UIView的两种方式。
1.使用 Interface Builder 方式。
这种方式,就是使用nib文件。通常我们说的“拖控件” 的方式。实际编程中,我们如果用Interface Builder 方式创建了UIView对象。那么,initWithFrame方法方法是不会被调用的。因为nib文件已经知道如何初始化该View。(因为,我们在拖该view的时候,就定义好了长、宽、背景等属性)。
这时候,会调用initWithCoder方法,我们可以用initWithCoder方法来重新定义我们在nib中已经设置的各项属性。这就是为什么使用initWithCoder的原因。
因为MSKView.xib的view是MSKView类型,而不是UIView类型了,所以其实是从nib中加载对象实例。

2.使用手动编码方式。
就是我们声明一个UIView的子类,进行“手工”编写代码的方式。
实际编程中,我们使用编程方式下,来创建一个UIView或者创建UIView的子类。这时候,将调用initWithFrame方法,来实例化UIView。
特别注意,如果在子类中重载initWithFrame方法,必须先调用父类的initWithFrame方法。在对自定义的UIView子类进行初始化操作。
比如:
- (id)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];// 先调用父类的initWithFrame方法
    if (self) {
        // 再自定义该类(UIView子类)的初始化操作。
        _scrollView = [[UIScrollView alloc] initWithFrame:self.bounds];
        [_scrollView setFrame:CGRectMake(0, 0, 320, 480)];
        _scrollView.contentSize = CGSizeMake(320*3, 480);
        
        [self addSubview:_scrollView];
    }
    return self;
}

当我们所写的程序里没用用Nib文件(XIB)时,用代码控制视图内容,需要调用initWithFrame去初始化

- (id)initWithFrame:(CGRect)frame{
    if (self =[superinitWithFrame:frame]) {
        // 初始化代码
    }
    return self;
}

用于视图加载nib文件,从nib中加载对象实例时,使用 initWithCoder初始化这些实例对象

- (id)initWithCoder:(NSCoder*)coder{
    if (self =[superinitWithcoder:coder]) {
        // 初始化代码
    }
    return self;
}

initWithCoder和initWithFrame的区别 :
1.initWithCoder: 对于.xib,当你嵌入一个视图对象到xib,视图加载时默认调用的是该方法;例如:假如创建的view来自nib,那么将会调用initWithCoder,由系统来调用,自己不能调用。
2.initWithFrame: 非.xib的手动编码,视图加载时默认调用的是该方法。是由自己调用,来初始化对象的

文档说明:The init method that gets used depends on how the view is created. It can be explicitly created using initWithFrame or it can be created by loading a nib. In that case,
the initWithCoder method gets called when the view is loaded from the nib. There are other init methods for subclasses (like UITableViewController has initWithStyle), so you have to be sure which one is being called. 

4.initWithNibName、initWithCoder、awakeFromNib的区分。

第一、initWithNibName 这个方法是在controller的类在IB中创建,但是通过Xcode实例化controller的时候用的. 

第二、initWithCoder 是一个类在IB中创建但在xocde中被实例化时被调用的.比如,通过IB创建一个controller的nib文件,然后在xcode中通过 initWithNibName来实例化这个controller,那么这个controller的initWithCoder会被调用.或者是一个view的nib文件,类似方法创建时调用initWithCoder 

第三、awakeFromNib 当.nib文件被加载的时候,会发送一个awakeFromNib的消息到.nib文件中的每个对象,每个对象都可以定义自己的awakeFromNib函数来响应这个消息,执行一些必要的操作。也就是说通过nib文件创建view对象时执行awakeFromNib

第四、关于initWithNibName 和 loadNibNamed 的区别和联系 : 
之所以要把这两者来一起讲,因为这两个方法,根本就不是一路货色,他们的联系:可以使用此方法加载用户界面(xib文件)到我们的代码中,这样,可以通过操作这个加载进来的(xib)对象,来操作xib文件内容。 下面进入主题,谈区别: 

1. ShowViewController的initWithNibName方法 
ShowViewController  *showMessage = [[ShowViewController alloc] initWithNibName:@"ShowViewController" bundle:nil]; 

2. ShowViewController的loadNibNamed方法 
NSArray  *nib = [[NSBundle mainBundle] loadNibNamed:@“MSKView” owner:self options:nil] ; 

总结: 只看他们初始化,那可能感觉是一样的。但是如果,打开分别看xib的关系的时候,才恍然大悟,原来他们的集成类都不一样。

1. initWithNibName要加载的xib的类为我们定义的视图控制器类。loadNibNamed要加载的xib的类为NSOjbect。
2.加载方式不同。
initWithNibName方法:是延迟加载,这个View上的控件是 nil 的,只有到 需要显示时,才会不是 nil 
loadNibNamed方法:即时加载,用该方法加载的xib对象中的各个元素都已经存在。 
(认真理解这句帮规:when using loadNibNamed:owner:options:, the File's Owner should be NSObject, the main view should be your class type, and all outlets should be hooked up to the view, not the File's Owner.) 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息