Метод awakeFromNib, вызываемый несколько раз

В моем проекте на основе 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 везде.

Ответ 1

Я нашел решение. awakeFromNib вызывается каждый раз, когда a NSTableCellView создается NSOutlineView.

Ответ 2

Основная причина описана в заголовочном файле NSTableView метода makeViewWithIdentifier: ".... Обратите внимание, что" владелец "будет получать вызов" awakeFromNib: "каждый раз, когда объект создается."

Мое решение прост, но я ожидаю, что он не подходит для всех: просто определите, например. tabelView как владелец:

- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
    NSTableCellView *view = [tableView makeViewWithIdentifier:kTextViewIdentifier owner:tableView];

    return view;
}

Ответ 3

Я не знаю, почему он называется четыре раза, но, по крайней мере, я могу объяснить два вызова awakeFromNib. Важно помнить, что awakeFromNib вызывается даже для владельца файла файла nib, а не только для объектов, содержащихся в файле nib.

Следовательно, ваш ResourceViewController awakeFromNib вызывается по меньшей мере дважды: когда он загружается в myDocument.xib, а затем, когда представление, управляемое ResourceViewController, загружается из другого nib.

Лучше выполнить инициализацию в других методах, которые вызывают более определенное время, например ...didLoad или applicationDidFinish....

Ответ 4

Я помещаю код внутри синхронизированного блока внутри моего 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 */
    }
}

Ответ 5

Я заметил то же самое в NSTableView. NSTableView был обновлен через NSArrayController, и я заметил, что NSTableView имеет делегат, заданный файловым владельцем. Когда я удалял делегата в File Owner, awakeFromNib вызывается только один раз.

Ответ 6

Это было нелегко понять, но для меня каким-то образом мой табличный вид изменился на "View Based" и "Cell Based" для режима содержимого.

Переключение на "Cell Based" и awakeFromNib выполнялось только один раз.

Примечание. Три раза выберите вид таблицы в Interface Builder, чтобы перейти на правильный уровень. Или просто выберите "Вид таблицы" в структуре документов.

Xcode Attributes Inspector

Ответ 7

Решение заключается не в том, чтобы установить владельца самостоятельно в makeViewWithIdentifier:owner:

Это приводит к тому, что awakefromNib вызывается несколько раз.