Ответ 1
Я нашел решение. awakeFromNib
вызывается каждый раз, когда a NSTableCellView
создается NSOutlineView
.
В моем проекте на основе NSPersistenDocument у меня есть структура, подобная этой
myDocument (NSPersistentDocument) -> myDocument.xib (windows xib)
|
|-> view (the self.view) --> ... "other view"
|
|-> some NSArrayController
|
|-> myResourceViewController --> myResourceViewController.xib
|
|-> view (the self.view)
|
|-> myTreeController (a NSTreeController subclass)
в основном, myResourceViewController - это экземпляр viewController, который управляет resourceView и управляет своими данными.
в awakeFromNib метод myDocument У меня есть следующий код
- (void)windowControllerDidLoadNib:(NSWindowController *)aController
{
...
[leftBar addSubview:resourceViewController.view]; //i add resourceViewController view
resourceViewController.view.frame = leftBar.bounds;
...
}
в методах myResourceViewController awakeFromNib у меня есть:
-(void)awakeFromNib;
{
NSLog(@"%@", [self description]);
[removeButton bind:@"enabled" toObject:resourceTreeController withKeyPath:@"selection" options:[NSDictionary dictionaryWithObject:NSIsNotNilTransformerName forKey:NSValueTransformerNameBindingOption]];
NSArray *draggedTypes = [NSArray arrayWithObjects:ResourceURIPasteBoardType, nil];
[resourceOutlineView registerForDraggedTypes:draggedTypes];
}
NSLog говорит, что awakeFromNib того же экземпляра myResourceViewController называется 4 раза, я не понимаю, почему. Мой единственный ResourceViewController создан в myDocument xib. Я не использую методы загрузки NSNib везде.
Я нашел решение. awakeFromNib
вызывается каждый раз, когда a NSTableCellView
создается NSOutlineView
.
Основная причина описана в заголовочном файле NSTableView метода makeViewWithIdentifier: ".... Обратите внимание, что" владелец "будет получать вызов" awakeFromNib: "каждый раз, когда объект создается."
Мое решение прост, но я ожидаю, что он не подходит для всех: просто определите, например. tabelView как владелец:
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
NSTableCellView *view = [tableView makeViewWithIdentifier:kTextViewIdentifier owner:tableView];
return view;
}
Я не знаю, почему он называется четыре раза, но, по крайней мере, я могу объяснить два вызова awakeFromNib
. Важно помнить, что awakeFromNib
вызывается даже для владельца файла файла nib, а не только для объектов, содержащихся в файле nib.
Следовательно, ваш ResourceViewController awakeFromNib вызывается по меньшей мере дважды: когда он загружается в myDocument.xib, а затем, когда представление, управляемое ResourceViewController, загружается из другого nib.
Лучше выполнить инициализацию в других методах, которые вызывают более определенное время, например ...didLoad
или applicationDidFinish...
.
Я помещаю код внутри синхронизированного блока внутри моего awakeFromNib так.
например
@implementation {
BOOL _initialize;
}
- (id)init {
self = [super init];
if (self) {
_initialize = YES;
}
return self;
}
- (void)awakeFromNib {
@synchronized(self) {
if (_initialize) {
_initialize = NO;
/* code to execute once */
}
}
/* code to re-execute */
}
}
Я заметил то же самое в NSTableView. NSTableView был обновлен через NSArrayController, и я заметил, что NSTableView имеет делегат, заданный файловым владельцем. Когда я удалял делегата в File Owner, awakeFromNib вызывается только один раз.
Это было нелегко понять, но для меня каким-то образом мой табличный вид изменился на "View Based" и "Cell Based" для режима содержимого.
Переключение на "Cell Based" и awakeFromNib выполнялось только один раз.
Примечание. Три раза выберите вид таблицы в Interface Builder, чтобы перейти на правильный уровень. Или просто выберите "Вид таблицы" в структуре документов.
Решение заключается не в том, чтобы установить владельца самостоятельно в makeViewWithIdentifier:owner:
Это приводит к тому, что awakefromNib вызывается несколько раз.