iPhone - не удается получить доступ к IBOutlet (нулевое значение)

У меня проблема с доступом к IBOutlet.

У меня есть NIB, внутри которого есть табличное представление, панель инструментов и UILabel (инкапсулированный в представление). Контроллер (то есть владелец файла) определяется как:

@interface ChoixPeriodeController : UIViewController <UITableViewDelegate> { 
 IBOutlet UILabel* __periodeInitialeLabel;
}

@property(nonatomic, retain) UILabel* periodeInitialeLabel;

- (void) setSelectedPeriode:(Tache_TypePeriode)typePeriode;

с @synthetize periodeInitialeLabel = __periodeInitialeLabel;

В файле .m эта функция вызывается родительским окном для инициализации метки:

- (void) setSelectedPeriode:(Tache_TypePeriode)typePeriode {
 NSMutableString* tmpString = [NSMutableString string];

 [tmpString appendFormat:some text format....];

 self.periodeInitialeLabel.text = tmpString;
}

В этой функции я вижу, что self.periodeInitialeLabel равен нулю. Я не понимаю, почему. Все подключено в ИБ... Видите, в чем может быть проблема?


person Oliver    schedule 15.01.2011    source источник
comment
Установите точку останова на viewDidLoad — что вызывается первым? viewDidLoad или setSelectedPeriode?   -  person makdad    schedule 15.01.2011
comment
@phooze: Хорошо ... Это setSelectedPeriode .... Мне придется иметь дело с еще одним атрибутом класса :-) Или у вас есть другое решение?   -  person Oliver    schedule 15.01.2011
comment
@Joe Blow: ты не можешь использовать все заглавные буквы во французском языке? Миру нужны от вас УДИВИТЕЛЬНЫЕ, НЕВЕРОЯТНО ПОТРЯСАЮЩИЕ ФРАНЦУЗСКИЕ МАТЕРИАЛЫ!!!!!   -  person MusiGenesis    schedule 15.01.2011
comment
@Джо: Марвин Хэмлиш? Могу ли я дать некоторые альтернативные рекомендации?   -  person MusiGenesis    schedule 15.01.2011
comment
@Joe Blow: первые символы подчеркивания здесь для предотвращения нежелательного доступа из кода. Когда я устаю, это предотвращает несколько минут поиска нежелательных прямых вызовов атрибута.   -  person Oliver    schedule 15.01.2011
comment
Попробуйте Shpongle и/или Banco de Gaia.   -  person MusiGenesis    schedule 15.01.2011
comment
@Джо Блоу: Да. делая это, я точно знаю, когда я получаю доступ к свойству или его установщику.   -  person Oliver    schedule 15.01.2011
comment
@phooze: не могли бы вы опубликовать свой комментарий в качестве решения, чтобы я мог его принять?   -  person Oliver    schedule 15.01.2011


Ответы (4)


Здесь вопрос в порядке действий. Если текстовая метка по-прежнему равна нулю, вероятно, она еще не настроена. Вместо этого вы можете вызвать этот метод внутри метода viewDidLoad UIViewController для обработки подобных операций, которые должны выполнять «дополнительную настройку», которую нельзя выполнить в Interface Builder.

Есть еще awakeFromNib. Они очень похожи, за исключением того, что awakeFromNib вызывается ONCE при распаковке NIB-файла. viewDidLoad можно вызывать много раз — например, если возникает ситуация с нехваткой памяти (часто происходит на iOS4), ваши представления будут очищены через viewDidUnload.

person makdad    schedule 16.01.2011

Для тех, у кого все еще есть проблемы с этим, я столкнулся с чем-то подобным даже в примере приложения. Ответ оказался таким:

UIImageView, созданный в построителе интерфейса, при необходимости устанавливается равным нулю

[self memberVar]

Загружает свойство, в то время как:

self.memberVar

Просто обращается к текущему значению, которое останется равным нулю. Поэтому я пытаюсь уйти от использования "." оператор. Это очень тонкая проблема, которую я в последнее время видел во многих примерах кода. Метод подчеркивания в новых примерах:

@synthesize memberVar = _memberVar;

по-прежнему просто оставляет переменную-член нулевой, пока вы не получите к ней доступ с помощью [self memberVar]. Я думаю, что Apple, возможно, пытается избежать этой проблемы, ссылаясь на _memberVar в реализации (например, в dealloc с [_imageView release])


ОБНОВЛЕНИЕ: Кроме того, если вы используете initWithNibName или loadNibNamed для загрузки контроллера из nib или xib на лету (например, пользовательский UITableViewCell), не забудьте вызвать:

[self loadView];

Это также загружает переменные-члены. Они не загружаются автоматически, если представление не отображается или не pushViewController на navigationController.

person Zack Morris    schedule 25.02.2012

Я думаю, что ваше свойство также должно быть определено с помощью IBOutlet, например:

@property(nonatomic, retain) IBOutlet UILabel* periodeInitialeLabel; 

и вам нужно @synthesize свойство в файле реализации, а затем убедиться, что periodeInitialeLabel правильно подключено в IB (т.е. не `__periodeInitialeLabel');

Обновление:

Если ваш оператор синтеза выглядит так:

@synthesize periodeInitialeLabel;

то это, вероятно, ваша проблема. Я думаю, что это должно быть так:

@synthesize periodeInitialeLabel = __periodeInitialeLabel;

чтобы подключить его к вашему полю.

person MusiGenesis    schedule 15.01.2011
comment
Эй, MusicGenesis, разве ты не должен делать ПОТРЯСАЮЩУЮ МУЗЫКУ, о которой мы говорили в другом посте? :) - person Fattie; 15.01.2011
comment
Эй, сегодня суббота. Могу ли я не иметь один выходной в неделю? - person MusiGenesis; 15.01.2011
comment
@Joe: только довольно уверен? :-) Не знаю - я вообще перестал пользоваться IB, и теперь я намного счастливее. - person MusiGenesis; 15.01.2011
comment
@Joe: Corona и подобные вещи обычно работают? Некоторые мои бывшие коллеги используют какие-то кроссплатформенные штуковины для создания отстойных приложений для iPhone, но я не знаю, потому ли это, что они отстой, или потому, что их фреймворк отстой. - person MusiGenesis; 15.01.2011
comment
ЭЙ ДЖО!!! ВАША МЫШЬ НЕ РАБОТАЕТ??? НЕ МОЖЕТ НАЙТИ СТРЕЛКУ ВВЕРХ РЯДОМ С МОИМ ОТВЕТОМ??? - person MusiGenesis; 15.01.2011

Учитывая этот интерфейс:

@interface ChoixPeriodeController : UIViewController <UITableViewDelegate> {    
    UILabel* __periodeInitialeLabel;
}

// I think it's more appropriate to mark a property with IBOutlet,
// rather than an ivar
@property(nonatomic, retain) IBOutlet UILabel* periodeInitialeLabel;

- (void) setSelectedPeriode:(Tache_TypePeriode)typePeriode;

// ...

@end

его реализация должна выглядеть так:

@implementation ChoixPeriodeController

@synthesize
periodeInitialeLabel = __periodeInitialeLabel;

// the rest of your implementation goes here
// ...

@end

Я бы также посоветовал вам ознакомиться с Руководством по стилю Google Objective-C. . Именование ваших иваров с двумя ведущими символами подчеркивания может быть не лучшим выбором.

person Alexei Sholik    schedule 15.01.2011
comment
Спасибо. Поскольку это не имеет побочных эффектов, я предпочитаю помечать ivar как IBOutlet, чтобы видеть, какие атрибуты важны в коде, а какие нет. Говоря о подчеркивании, я буду иметь дело со своим методом. Помещение подчеркивания в конце ничего не предотвратит из-за автозаполнения, из-за которого я могу делать ошибки. - person Oliver; 15.01.2011