Экземпляры IBOutlet становятся (нулевыми) после загрузки из NIB
-
12-09-2019 - |
Вопрос
Я работаю над приложением для iPhone и получаю (нулевые) ссылки на поля IBOutlet в моем контроллере.У меня есть подкласс UIViewController, который установлен в качестве владельца файла в моем XIB.У меня есть набор элементов пользовательского интерфейса, которые подключены к контроллеру.После загрузки из NIB и попытки установить свойства для этих элементов пользовательского интерфейса я обнаруживаю, что они равны (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.UITextView ExpandSearchPage.xib подключен к completeMessageView.
Когда я звоню
ExpandSearchPageController * searchExpanderPage = [[ExpandSearchPageController alloc] initWithNibName:@"ExpandSearchPage" bundle:[NSBundle mainBundle]];
[searchExpanderPage checkTextField];
в результате получается
"text field: (null)"
Решение
Я предполагаю, что, задав этот вопрос после более чем часового изучения проблемы, я пришел к ее разгадке:
Я просто изменил свой код, чтобы установить флажок в текстовом поле ПОСЛЕ отображения представления...теперь все создано в виде экземпляра.
Представьте себе , что:элементы пользовательского интерфейса не создаются до тех пор, пока вы их не отобразите!
Другие советы
Это и есть решение.
IBOutlets не готовы к использованию до тех пор, пока view controller не завершит загрузку.
Например, если вы хотите установить текстовое свойство UILabels, вам нужно сначала установить NSString на вашем контроллере, а затем установить текстовое свойство labels где-нибудь вроде 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 вашего SecondViewController:
@property (strong, nonatomic) IBOutlet UILabel *label;
@property (strong, nonatomic) NSString *stringForLabel;
Затем мы устанавливаем свойство text в UILabel, в viewDidLoad второго ViewController.m.На этом этапе IBOutlet создан и готов к запуску.
- (void)viewDidLoad {
[super viewDidLoad];
self.label.text = self.stringForLabel;
}
Другой потенциальной причиной нулевого указателя IBOutlet является забывание сохранить файл xib в Interface Builder после создания подключения к розетке.
Убедитесь, что свойство view вашего контроллера представления (в данном случае владельца файла ie) подключено к представлению в вашем xib.Поскольку ваше текстовое поле почти наверняка является подвидом этого, важно подключить и это (и я не думаю, что перо будет загружаться должным образом без этого параметра).
Вот как я это делаю:
//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];
}