从 NIB 加载后,IBOutlet 实例为空。

19

我正在开发一个iPhone应用程序,在我的控制器中获取到了IBOutlet字段的(null)引用。 我有一个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的File's Owner。ExpandSearchPage.xib的UITextView与completeMessageView连接。

当我调用

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

[searchExpanderPage checkTextField];

结果为

"text field: (null)"
5个回答

49

我猜在看了一个小时的问题后提出问题,让我想到了解决方法:

我刚刚将我的代码更改为在显示视图后检查文本框... 现在一切都已实例化。

想象一下:UI元素直到您显示它们才被实例化!


另一个引起我的兴趣的点是,当使用 presentViewController:animated:completion: 模态呈现视图控制器时,直到视图出现(正如你所发现的那样),所有的 IBOutlets 都将为 nil。因此,您需要通过完成块访问它们,在模态上调用 viewDidAppear 时会调用该块。 - abc123

5

这是解决方案。

直到视图控制器完成加载,IBOutlets 才可以使用。

例如,如果您想设置 UILabel 的文本属性,您需要首先在控制器上设置 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";
}

然后在你的第二个视图控制器(.h文件)中:

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

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

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

3

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


1
我相信这是XCode早期版本中的一个问题——%-R没有自动保存。现在已经解决了。仍然要注意这个问题,给你加一分。 - mobibob

0

这是我的做法:

//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];
}

0

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接