从 NIB 加载后 IBOutlet 实例为(空)

Posted

技术标签:

【中文标题】从 NIB 加载后 IBOutlet 实例为(空)【英文标题】:IBOutlet instances are (null) after loading from NIB 【发布时间】:2009-08-11 01:09:38 【问题描述】:

我正在开发一个 iPhone 应用程序,并且在我的控制器中获得了对 IBOutlet 字段的(空)引用。我有一个 UIViewController 子类,它在我的 XIB 中设置为文件的所有者。我有一组连接到控制器的 UI 元素。从 NIB 加载并尝试在这些 UI 元素上设置属性后,我发现它们是 (null)。为了澄清,一些代码:

ExpandSearchPageController.h:

@interface ExpandSearchPageController : UIViewController

  IBOutlet UITextView * completeMessageView;


-(void)checkTextField;

@property (nonatomic, retain) IBOutlet UITextView * completeMessageView;

ExpandSearchPageController.m:

@implementation ExpandSearchPageController

@synthesize completeMessageView;

-(void)checkTextField

  NSLog(@"text field: %@",completeMessageView);

ExpandSearchPageController 被设置为 ExpandSearchPage.xib 的文件所有者。 ExpandSearchPage.xib 的 UITextView 连接到 completeMessageView。

当我打电话时

ExpandSearchPageController * searchExpanderPage = [[ExpandSearchPageController alloc] initWithNibName:@"ExpandSearchPage" bundle:[NSBundle mainBundle]];

[searchExpanderPage checkTextField];

结果是

"text field: (null)"

【问题讨论】:

【参考方案1】:

我想在看了一个多小时后提出这个问题让我想通了:

我刚刚更改了代码以在显示视图后检查文本框...现在所有内容都已实例化。

想象一下:UI 元素在您显示它们之前不会被实例化!

【讨论】:

另一个吸引我的兴趣点。当以presentViewController:animated:completion: 模态显示视图控制器时,所有 IBOutlets 将为零,直到视图出现(您发现的内容)。所以你需要通过完成块来访问它们,当viewDidAppear在模式上被调用时,它会被调用。【参考方案2】:

这就是解决方案。

在视图控制器完成加载之前,IBOutlets 无法使用。

例如,如果要设置 UILabels 文本属性,则需要先在控制器上设置 NSString,然后在 viewDidLoad 之类的地方设置标签文本属性。

所以在你的 firstViewController.m 中:(这是用于情节提要,但同样的想法适用)

- (void)buttonPress:(id)sender 
   [self performSegueWithIdentifier:@"mySegue" sender:self];


- (void)prepareForSegue(UIStoryboardSegue *)segue sender:(id)sender 
   SecondViewController *secondViewController = [segue destinationViewController];
   secondViewController.stringForLabel = @"My Label String";

然后在你的 secondViewController 的 .h 中:

@property (strong, nonatomic) IBOutlet UILabel *label;
@property (strong, nonatomic) NSString *stringForLabel;

然后我们设置UILabel上的text属性,在secondViewController.m的viewDidLoad中。 到此阶段,IBOutlet 已创建并准备就绪。

- (void)viewDidLoad 
   [super viewDidLoad];
   self.label.text = self.stringForLabel;

【讨论】:

【参考方案3】:

空 IBOutlet 指针的另一个潜在原因是在创建出口连接后忘记在 Interface Builder 中保存 xib 文件。

【讨论】:

我认为这是 XCode 早期版本中的一个问题—— %-R 没有自动保存。现在确实如此。仍然需要注意 +1。【参考方案4】:

确保视图控制器的视图属性(在这种情况下为文件所有者)已连接到 xib 中的视图。由于您的 textField 几乎可以肯定是它的子视图,因此连接它也很重要(而且我认为如果没有设置,笔尖将无法正确加载)。

【讨论】:

【参考方案5】:

这就是我的做法:

//in your view controller
-(void)setUp

    [self.cardView layoutIfNeeded];
    LearnCardPlainText *cardNib = [[[UINib nibWithNibName:@"LearnCardPlainText" bundle:nil] instantiateWithOwner:self options:nil] objectAtIndex:0];
    cardNib.frame = self.cardView.frame;
    [cardNib setUpWithPart:learnModel];
    [self.view addSubview:cardNib];

【讨论】:

以上是关于从 NIB 加载后 IBOutlet 实例为(空)的主要内容,如果未能解决你的问题,请参考以下文章

从 NIB 为 GeoLocation 加载/创建视图 - IOS 和 MapKit

UITableView (IBOutlet) 在初始数据加载后变为空

使用 OCMock 检查 IBOutlet 连接

Cocoa - 将 IBOutlet 链接到单独的 Nib

为啥我必须在自定义 NIB / XIB 中连接 IBOutlet 两次?

IBOutlet 未在 Cocoa MVC 项目中设置