Question

I am working on an iPhone app and am getting (null) references to IBOutlet fields in my controller. I have a UIViewController subclass that is set as the File's Owner in my XIB. I have a set of UI elements that are wired into the controller. After loading from NIB and attempting to set properties on those UI elements, I find that they are (null). To clarify, some code:

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 is set as the File's Owner for ExpandSearchPage.xib. ExpandSearchPage.xib's UITextView is wired to the completeMessageView.

When I call

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

[searchExpanderPage checkTextField];

the result is

"text field: (null)"
Was it helpful?

Solution

I guess asking the question after looking at the problem for over an hour led me to figure it out:

I just changed my code to check the text box AFTER displaying the view... now everything is instantiated.

Imagine that: the UI elements aren't instantiated until you display them!

OTHER TIPS

This is the solution.

The IBOutlets aren't ready to use until the view controller finishes loading.

For example, if you want to set a UILabels text property, you would need to set a NSString on your controller first, and then set the labels text property in somewhere like viewDidLoad.

So in your firstViewController.m : (This is for storyboards, but same idea applies)

- (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";
}

Then in the .h of your secondViewController:

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

Then we set the text property on the UILabel, in the viewDidLoad of secondViewController.m. By this stage, the IBOutlet has been created and is ready to go.

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

Another potential cause of a null IBOutlet pointer is forgetting to save the xib file in Interface Builder after creating the outlet connection.

Make sure the view property of your view controller (ie File's Owner in this case) is wired to the view in your xib. As your textField is almost certainly a subview of that, it's important to get that wired in too (and I don't think the nib will load properly without that being set).

This is how I do it:

//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];
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top