总结Nib(xIB)、File's owner、NSBundle、loadView/viewDidLoad、initWithNibName的相关基础知识

什么是Nib文件

【注:不准确地讲,就是一个可以往里面拖控件的界面设计文件】

Nib(也叫Xib)文件是一种特殊类型的资源文件,它用于保存iPhone OS或Mac OS X应用程序的用户接口。Nib文件是Interface Builder文档。通常您会使用Interface Builder设计应用程序的可视部分-例如窗口或视图。有些时候,您可能也用它来配置一些不可视的对象,例如控制器对象(用于管理窗口和视图)。实际上,所有这些操作都是在编辑一份Interface Builder文档,即在创建一份对象图。保存文件的时候,就是将该对象图进行归档,加载文件的时候,就是将对象图进行解档。


Nib文件—也就是对象图-可以包含占位对象,这种对象用于指涉存在于文档之外的对象。这些对象虽然不在文档中,但却可能含有文档内对象的引用,或者被文档内的对象引用。文件拥有者就是一种特殊的占位对象。


在程序运行的时候,您可以使用 loadNibNamed:owner:(或者此方法变种)加载Nib文件。在Nib文件中,文件拥有者是个占位对象,它表示您通过owner参数传给此方法的对象。加载Nib文件的时候,所有在Interface Builder中建立的关联(文件拥有者和其他对象之间的关联)都能够在运行时重新建立起来。


nib文件是一种数据文件,用于存储可在应用程序需要时使用的一些“冻结”的对象。大多数情况下,应用程序使用nib文件来存储构成用户界面的窗口和视图。当您将nib文件载入应用程序时,nib装载代码会将文件中的内容转化为应用程序可以操作的真正对象。通过这个机制,nib文件省去了用代码创建那些对象的工作。


Interface Builder是一个可视化的设计环境,您可以用它来创建nib文件。您可以将标准对象(比如UIKit框架中提供的窗口和视图)和Xcode工程中的定制对象放到nib文件中。在Interface Builder中创建视图层次相当简单,只需要对视图对象进行简单拖拽就可以了。您也可以通过查看器窗口来配置每个对象的属性,以及通过创建对象间的连接来定义它们在运行时的关系。您所做的改变最终都会作为nib文件的一部分存储到磁盘上。


在运行时,当您需要nib文件中包含的对象时,就将nib文件装载到程序中。典型情况下,装载nib文件的时机是当用户界面发生变化和需要在屏幕上显示某些新视图的时候。如果您的应用程序使用视图控制器,则视图控制器会自动处理nib文件的装载过程,当然,您也可以通过类的方法自行装载。




主Nib文件
初始化的另一个任务是装载应用程序的主nib文件。如果应用程序的信息属性列表(Info.plist)文件中含有NSMainNibFile键,则作为初始化过程的一个部分,UIApplication对象会装载该键指定的nib文件。主nib文件是唯一一个自动装载的nib文件,其它的nib文件可以在稍后根据需要进行装载。


Nib文件是基于磁盘的资源文件,用于存储一或多个对象的快照。iPhone应用程序的主nib文件通常包含一个窗口对象和一个应用程序委托对象,还可能包含一个或多个管理窗口的其它重要对象。装载一个nib文件会使该文件中的对象被重新构造,从而将每个对象的磁盘表示转化为应用程序可以操作的内存对象。从nib文件中装载的对象和通过编程方式创建的对象之间没有区别。然而,对于用户界面而言,以图形的方式(使用Interface Builder程序)创建与用户界面相关联的对象并将它们存储在nib文件中通常比以编程的方式进行创建更加方便。


(文章出处:http://blog.csdn.net/henry_sea/article/details/6708553


-----------------------------------------


(一)XIB的适用范围:

xib(也叫Nib)与storyboard一样是用来描述界面的。

storyboard描述的是比较大型的,大范围.适合描述界面跳转等.


(二)XIB的使用:

Xib是小范围的的,是轻量级的.比较适合描述小块的界面.


(节选自:http://blog.csdn.net/xn4545945 


(三)initWithNibName与loadNibNamed方法的区别:


1.initWithNibName要加载的xib的类为我们定义的视图控制器类 
  loadNibNamed要加载的xib的类为NSOjbect。
(比如:甲,乙都买了一个iPhone,但是,甲的是自己的钱,而乙用的是某某的钱)
 


2.加载方式不同
 initWithNibName方法:是延迟加载,这个View上的控件是 nil 的,只有到 需要显示时,才会不是 nil
loadNibNamed方法:即时加载,用该方法加载的xib对象中的各个元素都已经存在。
(认真理解这句帮规:whenusing loadNibNamed:owner:options:, the File's Owner should be NSObject, themain view should be your class type, and all outlets should be hooked up to theview, not the File's Owner.)


(节选自:http://blog.csdn.net/zengraoli/article/details/12882017


-------------------------


关于File’s Owner

作用: 

让xib也能像storyboard一样连线. (storyboard默认生成的时候,class为对应的viewController,因此能直接和代码中方法进行连线)。
做法:
将xib中的Class设置为对应的viewController.并在loadNib时将owner设置为对应的viewController(即一般为self, 对象)。
File’Owner不限于viewController,可以是任何类.Class定义为哪个类,就能在哪个类中进行连线, 而要在loadNib时owner传入相应的对象即可调用相应方法。(必须保持一致,否则调用方法时会出现找不到方法)


节选自:http://blog.csdn.net/xn4545945 (文字有改动)


-----------------------------------------


NSBundle


    无论开发OS X应用,还是开发iOS 应用,如果应用程序使用绝对路径或相对路径去访问文件,则必然导致程序的可移植性降低。因为把这个应用程序部署到客户机上使用时,客户机对应的路径下可能根本没有这些文件。
    为了提高OS X应用或iOS应用的可移植性,可以把项目资源文件放在应用中,让应用自包含这些资源文件。当应用自包含这些资源文件之后,接下来就可使用NSBundle来访问这种应用自包含的资源文件了。
    在OS X应用或iOS应用中添加资源非常简单,只要把文件拖到Xcode左边的项目导航面板中,当出现对话框时,通常选择复制资源文件到项目中,这样该项目就会自包含该资源文件。
    为了获取NSBundle对象,一般会调用该类的mainBundle方法,该方法就会返回该应用对应的应用程序包。


(出处:《疯狂iOS讲义(上)》P325)


-------------------------


iOS开发里的Bundle是个啥玩意?!


初学iOS开发的同学,不管是自己写的,还是粘贴的代码,或多或少都写过下面的代码

[[NSBundle mainBundle] pathForResource:@"someFileName" ofType:@"yourFileExtension"]; 
[YourViewController initWithNibName:"YourViewController" bundle:nil];

可是你知道这里的bundle到底是个啥玩意呢?!

Bundle简单地讲,就是一个内部结构按照标准规则组织的特殊目录

iOS的应用都是通过bundle进行封装的,对应的bundle类型是Application类型,平时我们通过XCode编译出来的Target(即我们开发的应用),其实就是一个Application类型bundle,即一个文件夹!但是Finder会把这个bundle当做一个文件显示给我们,其实是因为这个bundle自身也是一个package,而Mac系统会把所有的package当做一个文件来对待,显示给用户,从而防止用户误操作导致程序文件损坏或丢失。至于bundle和package有什么区别,就不在这里展开说明了,本文后面所说的bundle都会被Mac系统视为package。

现在我们已经知道了,原来我们开发的应用程序,最后都会成为一个bundle,那么就不难理解为什么很多资源文件加载大多是通过bundle来进行的了,从bundle进行文件加载实际就是通过应用自己所在的文件夹进行加载。

不过紧接着我们又会产生好几个疑问:


1 为什么不直接使用文件路径的方式来读取资源文件呢?


2 为什么还会存在pathForResource:ofType:这个方法,难道说我们在开发的时候还不能确定这些文件在哪儿吗?


事实上,我们是可以使用文件系统的路径进行资源文件的访问的,不过当我们要进行App的国际化的时候,我们需要自己去实现不同语言、地区情况下加载对应的文件,而在部分资源文件公用,部分需要国际化的时候,对开发人员来讲,代码维护起来尤为混乱。

而bundle对iOS开发者来讲,最大的方便就是可以非常简单地让自己的应用国际化,在不同的语言不同的地区,加载不同的资源文件,显示不同的语言文字,而实现这些只需要我们严格按照bundle的要求进行资源文件的存放即可,而不需要写大量代码判断地区语言。遵循的方法也很简单,只需要我们创建对应的"本地化文件夹"即可,例如我们要同时让图片"pic.png"在中文和英文下显示不同的内容,只需要创建两个本地化文件夹zh.lproj和en.lproj,分别放入同名但内容不同的"pic.png"即可。

关于如何让自己的应用国际化的具体方法,将在之后的文章进行描述。 


(文章出处:http://www.cnblogs.com/BigPolarBear/archive/2012/03/28/2421802.html


-----------------------------------------


iOS开发之loadView和viewDidLoad总结


iPhone开发必不可少的要用到这两个方法。
他们都可以用来在视图载入的时候,初始化一些内容。 但是他们有什么区别呢?


loadView
此方法在控制器的view为nil的时候被调用。 此方法用于以编程的方式创建view的时候用到。loadView是使用代码生成视图的时候,当视图第一次载入的时候调用的方法。用于使用(写)代码来实现控件。用于使用代码生成控件的函数。


viewDidLoad
此方法只有当view从nib文件初始化的时候才被调用。viewDidLoad用于初始化,加载时用到的。如:


- (void) loadView {
 UIView *view= [ [ UIView alloc] initWithFrame:[ UIScreen mainScreen] .applicationFrame] ;
 [ view setBackgroundColor:_color] ;
 self.view = view;
 [ view release] ;
}


(节选自: http://www.1000phone.net/forum.php?mod=viewthread&tid=10507&extra=page%3D1%26filter%3Dauthor%26orderby%3Ddateline%26orderby%3Ddateline


-----------------------------------------


initWithNibName


iOS中init一个对象时,会调用对象的init方法,进入init方法时会调用initWithNibName方法,可调试验证:


// 以后自定义控制器建议写这个方法,让控制器一创建出来就拥有某些属性
// init方法内部默认会调用initWithNibName方法
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
         
    }
    return self;
}

(文章出处: http://www.daxueit.com/article/4387.html


[[MyViewController alloc] initWithNibName:nil bundle:nil]; 搜索 Nib 文件的规则及注意事项:


如果:- initWithNibName:bundle:  的第一个参数, 即 nibName 指定为 nil, 并且没有重写 - loadView方法, 则 view controller 按下列顺序在 mainBundle 中 (因第二个参数 nibBundle 也指定为 nil) 搜索 NIB 文件: 【注:假设当前的view controller(控制器)命名为MyViewController】


1. 先搜索 MyView.nib, 如果有, 就用它的内容初始化MyViewController 对象;


2. 如果没有搜到 MyView.nib, 就搜索 MyViewController.nib, 找到后就用它初始化 MyViewController 对象;


3. 如果还有找到, 就是说, 没有与该 view controller 关联 (associated) 的 NIB 文件, 并且因用户没有重写 - loadView  方法, 所以 - loadView  的默认实现就创建一个 plain UIView object, 并将它设定为当前 view controller 的 view ;


[备注 1] 如果 - initWithNibName:bundle: 的参数 nibName 指定了 NIB 文件的名字, 但该 NIB 文件在参数 nibBundle 指定的 bundle 中找不到, App 将 Crash, 异常提示信息形如:


*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle: 'NSBundle </Users/Qi/Library/Application Support/iPhone Simulator/5.1/Applications/4AD1619B-1AA7-4E6D-B67A-18C2AA1A8494/testUIViewController.app> (loaded)' with name 'MyViewController''  

[备注 2] - initWithNibName:bundle: 的参数 nibName 指定的 NIB 文件不是在该方法被调用时立刻加载的, 而是当 view controller 的 view 被访问时才首次被加载, 该初始化方法的调用是设定了: @property(nonatomic, readonly, copy) NSString *nibName;  的值.


[备注 3] 假如用户按下面三种情况重写 (override) 了 - loadView 方法: 


(1). 重写, 但不做任何事情: 


- (void)loadView  
{  
}  


那么, 无论在 - initWithNibName:bundle: 中是否指定了有效的 nibName 名, view controller 的 view 都没有被设定, 还是默认值 nil, 同时得到如下控制台打印信息 (设用 MyViewController 对象来设定 window 的 rootViewController): 

Application windows are expected to have a root view controller at the end of application launch



(2). 重写, 调用父类的方法 (注: - loadView 的说明中提到: Your custom implementation of this method should not call super.).


- (void)loadView  
{  
    [super loadView];  
}  

那么, 如果在 - initWithNibName:bundle: 中指定了 nibName 为有效的 NIB 名, 就用该 NIB 中的 view 设置 view controller 的 view property; 如果指定了 nibName 为 nil, 则重写方法中父类的方法会创建一个 plain UIView object 来设定 view controller 的 view property. 


(3). 重写, 按需求重建用户自己的 view (hierarchy). 如:

- (void)loadView  
{  
    self.view = [[[UIViewalloc] initWithFrame:[[UIScreenmainScreen] applicationFrame]] autorelease];  
    self.view.backgroundColor = [UIColor greenColor];  
}  

那么, 无论在 - initWithNibName:bundle: 中是否指定了有效的 nibName 名, view controller 的 view 都是由 - loadView 方法中来设定, 而不去理会那个 NIB 文件中预设的 view. 


(文章出处:http://blog.csdn.net/honood/article/details/7816084#,有补充)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值