Является ли -makeWindowControllers лучшим местом для инициализации NSPersistentDocument? - PullRequest
1 голос
/ 12 октября 2011

При загрузке существующего документа с использованием NSPersistentDocument, в рамках инициализации я хотел бы подготовить некоторый контент:

    NSFetchRequest *req = [NSFetchRequest fetchRequestWithEntityName:@"DocumentRoot"];
    NSArray *results = [self.managedObjectContext executeFetchRequest:req error:NULL];
    if (results.count) self._docRoot = [results objectAtIndex:0];

Когда я помещаю этот код в -init, запрос на выборку не возвращает никаких результатов.

Я столкнулся с этой проблемой при рефакторинге компонентов контроллера вида из моего подкласса NSPersistentDocument в новый подкласс NSWindowController. Я имел обыкновение обрабатывать эту инициализацию в -windowControllerDidLoadNib:, но это больше не вызывается.

Если я переместу код с -init на -makeWindowControllers, я получу ожидаемые результаты. -makeWindowControllers действительно правильное место для подготовки такого контента?

Ответы [ 3 ]

5 голосов
/ 31 января 2012

Исходя из полученных ответов, я думаю, что поступаю правильно, поэтому вот мой ответ на мой собственный вопрос.

Если вы используете стек основных данных, предоставленныйNSPersistentDocument, вы не можете использовать Базовые данные в -init.

Вместо этого вы должны:

  1. Поместить код инициализации документа непосредственно в -windowControllerDidLoadNib: - или еслиВы используете пользовательский подкласс NSWindowController в -makeWindowControllers.
  2. . Вы также можете абстрагировать код инициализации документа в вспомогательный метод с некоторым уникальным именем, например -setUpDocument, и вызывать этот метод из -makeWindowControllers / -windowControllerDidLoadNib: вместо.

Если вы используете простой NSDocument или настраиваете базовый стек данных самостоятельно, вы можете настроить модель документа в -init.

1 голос
/ 06 января 2012

Из этого вопроса и вашего связанного вопроса о NSArrayControllers я понял, что вы делаете что-то вроде этого:

- (void)makeWindowControllers
{
    MyWindowController* wc = [[[MyWindowController alloc] initWithWindowNibName: [self windowNibName]] autorelease];
    [self addWindowController: wc];
}

Когда вы сделаете это, -windowControllerDidLoadNib: не будет вызван, потому что объект NSDocument не является владельцем Nib, если вы инициируете таким образом. Если вы посмотрите на NSDocument.h, то увидите следующий комментарий (см. Добавленный акцент):

/* Create the user interface for this document, but don't show it yet. The
default implementation of this method invokes [self windowNibName],
creates a new window controller using the resulting nib name (if it is
not nil), **specifying this document as the nib file's owner**, and then
invokes [self addWindowController:theNewWindowController] to attach it.
You can override this method to use a custom subclass of
NSWindowController or to create more than one window controller right
away. NSDocumentController invokes this method when creating or opening
new documents.
*/
- (void)makeWindowControllers;

Если вы вместо этого сделаете это:

- (void)makeWindowControllers
{
    MyWindowController* wc = [[[MyWindowController alloc] initWithWindowNibName: [self windowNibName] owner: self] autorelease];
    [self addWindowController: wc];
}

Полагаю, вы обнаружите, что -windowControllerDidLoadNib: снова вызывается. Это может не помочь вам, если у вас есть веская причина, по которой владелец этого Nib не является NSDocument, но именно поэтому -windowControllerDidLoadNib: не вызывается, и что вы можете сделать, чтобы вернуть это поведение. Это почти наверняка лучшее место для выполнения выборок, чем в init, что, вероятно, происходит до того, как все необходимые средства поддержки CoreData будут в наличии. Так что это один из вариантов.

0 голосов
/ 28 ноября 2011

Если код не вызывается из init, это потому, что ваш документ инициализируется в другом месте, например initWithContentsOfURL:ofType:error:, initForURL:withContentsOfURL:ofType:error:, initWithType:error: или initWithCoder: makeWindowControllers, не для настройки ваших данных. Попробуйте реализовать все вышеперечисленные инициализаторы и зарегистрируйтесь, чтобы узнать, кто из них вызывается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...