再看《ios编程》的时候看了关于xib关联与加载相关的知识,也通过测试发现了一些问题,使我对这方面的知识有了进一步的理解。
1.我们需要一些方式来连接从xib文件加载进来对象到已经存在内存中的对象(如:UIViewController),这样我们就可以设置对象(UIController)的view变量指向从xib加载到的view。这时候就有了File’Owner这个概念。(Instead, we need some way to connect objects loaded from the XIB file to objects that exist in memory before the XIB file is loaded. This way, the already existing CurrentTimeViewController could set its view instance variable to point at the view loaded from this XIB file. This is where the File's Owner comes in)
2.File’Owner是一个占位对象,当xib被加载进来时不会创建占位对象的实例,你可以想象成这只是用来放置已有对象的位置,是为了使对象(如UIViewController)与xib之间建立连接。(The File's Owner is a placeholder object. When a XIB file is loaded, placeholder objects are not instantiated. You can think of a placeholder object as a hole in which existing objects can be placed so that connections can be made between them and the objects in the XIB file.)
3.那xib文件又是怎样在创建UIViewController时被加载进来的呢?当你创建对象,调用init消息时init里会[super initWithNibName:bundle:],向父类发送这个消息,传入xib文件名,当UIViewController需要使用view时,加载view会调用LoadView方法,方法的实现:会在指定的xib文件中找,如果传入xibName为nil,那么UIViewController就会查找和这个UIViewController子类类名匹配的xib文件。当然也可以强制指定需要载入的xib文件。(So, how does this work? When you create an instance of a UIViewController subclass, you pass it the name of a XIB file through its designated initializer, initWithNibName:bundle:. When the view controller is asked for its view, it checks to see if a XIB file with that name exists in your application bundle. (If you specify nil as the name, it will search for a XIB file whose name matches the name of the view controller subclass.) It then loads that XIB file)
如:
- (id)init
{
self = [super initWithNibName:@"CurrentTimeViewController"
bundle:nil];
if (self) {
UITabBarItem *tbi = [self tabBarItem];
[tbi setTitle:@"Time"];
UIImage *i = [UIImage imageNamed:@"Time.png"];
[tbi setImage:i];
}
return self;
}
后来我看到了LoadView中的大致实现:
- (void)loadView
{
// If a nibName was passed to initWithNibName:bundle:...
if ([self nibName]) {
// Load that nib file, with ourselves as the file's owner, thus connecting
// the view outlet to the view in the nib
[[NSBundle mainBundle] loadNibNamed:[self nibName] owner:self options:nil];
}
else {
// What is the name of this class?
NSString *className = NSStringFromClass([self class]);
// What's the full path of the nib file?
NSString *nibPath = [[NSBundle mainBundle] pathForResource:className
ofType:@"nib"];
// If there really is a nib file at that path, load it
if ([[NSFileManager defaultManager] fileExistsAtPath:nibPath]) {
[[NSBundle mainBundle] loadNibNamed:className owner:self options:nil];
}
else {
// If there is no nib, just create a blank UIView and set it as the view
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
[self setView:view];
[view release];
}
}
}
4.loadView方法负责执行载入xib,这个方法的默认实现是检查并载入xib文件,所以当一个controller通过xib文件加载view变量时,不要覆盖loadView方法,如果你想要用代码来创建view时就必须覆盖loadView方法避免从xib文件中加载。(The loadView method is responsible for this XIB loading behavior. The default implementation of this method does the checking for and loading of a XIB file. Therefore, when a view controller is loading its view from a XIB file, you do not override loadView. If instead you want to create a view for a view controller programmatically, you must override loadView so it does not load a XIB file.)
5.我在测试过程中还遇到了一个问题,就是在AppDelegate中添加xib文件时(MainWindow),我把1.Feild's Owner设置为UIApplication 2.在xib中添加一个object控件(黄色正方体那个)并设置为AppDelegate.3.关联号好AppDelegate和window。但是还是不能显示xib,并在application:didFinishLaunchingWithOptions:中打印window,结果为空。为什么不行呢?后来才想到原来虽然设置了关联,但是xib文件没有加载,就是说没有添加加载xib文件的语句。这时候有一个方便的方法就是在App-Info.plist文件里添加一项(点击“+”会有下拉列表可供选择):key为:Main nib file base name(Iphone) value为:MainWindow(nib文件的名字)。
其实属性文件(plist文件)会在开发的过程中带来很大方便,有很多的属性可以先在plist文件中先设置,然后通过代码得到plist文件,再通过键值对来取值进行相应的配置。App-Info.plist(应用配置信息属性列表)利用的应该就是这个原理吧。在很多项目也会建立一个plist文件用来存放一些属性。我之前跟着视频做的微博项目中也用过。(微博项目以后再总结)。