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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/kmyhy/article/details/82810512

故事板是在 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。

  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 了:

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

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

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

    
    TestViewController* vc = [TestViewController new];

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

效果也是一样的。

猜你喜欢

转载自blog.csdn.net/kmyhy/article/details/82810512