在故事板中加载 nib 时 IBOutlet 为 nil

栏目: IOS · 发布时间: 6年前

内容简介:故事板是在 iOS 5 开始出现的,在此之前我们使用的是 nib/xib。一个故事板支持多个 ViewController,同时可以在这些 ViewController 中进行连接(segue)。但是随着工程中 ViewController 的增加,故事板中 ViewController 之间的连线变得纷乱复杂,故事板也就失去了原来的意义。与之相比较,nib/xib 只支持单一的 ViewController,这种因为简单带来的清晰使得它在项目中仍然被大量使用。但是,如果在项目中混合使用故事板和 nib

故事板是在 iOS 5 开始出现的,在此之前我们使用的是 nib/xib。一个故事板支持多个 ViewController,同时可以在这些 ViewController 中进行连接(segue)。但是随着工程中 ViewController 的增加,故事板中 ViewController 之间的连线变得纷乱复杂,故事板也就失去了原来的意义。与之相比较,nib/xib 只支持单一的 ViewController,这种因为简单带来的清晰使得它在项目中仍然被大量使用。

但是,如果在项目中混合使用故事板和 nib 文件,可能会带来一些意想不到的问题。一个典型的问题是,storyboard 加载 nib 中的 view controller 时,这个 view controller 中的 IBOutlet 都会丢失连接,这样在 viewDidLoad 后,所有的 IBOutlet 属性都为 nil,你根本无法使用这些属性。你可以来看一个例子。

  1. 新建一个 Single View 项目。

  2. 新建一个 UIViewController 子类,名字叫做 TestViewController,确认勾上 Also create xib file。

  3. 打开 TestViewController.xib 文件,拖入一个 label,为这个按钮建立一个到 IBOutlet 属性 label 的连接。

  4. 在 TestViewController.m 的 viewDidLoad 方法中,加入这句:

    _label.text = @"我是一个 Label";

    同时在这句上打一个断点。

  5. 打开 Main.storyboard。在 ViewController 上放一个按钮。title 设置为“下一步”。

  6. 拖入一个 UIViewController。 将 Class 改成 TestViewController。

  7. 使用 Embed in Navigation Contorller,将 View Controller 外面套上一个导航控制器。

  8. 在 View Controller 和 TestViewController 之间添加一个 segue,ID 不妨叫做 test。

    在故事板中加载 nib 时 IBOutlet 为 nil
  9. 为 View Controller 上的“下一步”按钮创建一个 IBAction buttonClicked,在里面编写代码:

    -(void)buttonClicked{
    [self performSegueWithIdentifier:@"test" sender:nil];

这样,当按钮一点击,导航控制器会跳到 TestViewController。

Build & run,点击“下一步”按钮,断点停下,将鼠标放在 _label 变量上查看值,发现值为 nil,继续执行,Label 上的文字不会改变。

这个问题说明,故事板在加载 nib 文件时,不会自动加载 nib 文件中的内容。为了搞清楚故事板是如何加载 TestViewController 类的,我们在 TestViewController.m 中增加两个初始化方法,并在每个方法中打上断点:

-(instancetype)initWithCoder:(NSCoder *)aDecoder{
    self = [super initWithCoder:aDecoder];
    
    return self;
}
-(instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{
    return [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
}

Build & run,我们发现断点在 initWithCoder: 方法中停下。说明故事板是调用这个方法来初始化 TestViewController 的。

我们将这个方法修改为:

-(instancetype)initWithCoder:(NSCoder *)aDecoder{
    self = [super initWithNibName:NSStringFromClass([self class]) bundle:nil];
    
    return self;
}

这样,故事板就会从 nib 文件中加载 TestViewController 了。Build & run,当断点停下,观察 _label 变量,现在它不再为 nil 了:

在故事板中加载 nib 时 IBOutlet 为 nil

继续执行,TestViewController 上 Label 的文字成功被我们改变成“我是一个 Label”。

当然,我们也可以用代码创建 TestViewController, 而不是让故事板为我们创建 TestViewController。

在 Main.storyboard 中删除 Test View Controller,然后修改 View Controller 的 buttonClicked 方法:

TestViewController* vc = [TestViewController new];

    [self.navigationController pushViewController:vc animated:YES];

效果也是一样的。


以上所述就是小编给大家介绍的《在故事板中加载 nib 时 IBOutlet 为 nil》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Essential C++中文版

Essential C++中文版

[美] Stanley B. Lippman / 侯捷 / 华中科技大学出版社 / 2001-8 / 39.80元

书中以4个面向来表现C++的本质:procedural(程序性的)、generic(泛型的)、object-based(个别对象的)、object-oriented(面向对象的),全书围绕着一系列逐渐繁复的程序问题,以及用以解决这些问题的语言特性。循此方式,读者不只学到C++的函数和结构,也会学习到它们的设计目的和基本原理。一起来看看 《Essential C++中文版》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具