Is -makeWindowControllers the best place to initialize an NSPersistentDocument?

。_饼干妹妹 提交于 2019-12-06 14:51:36

问题


When loading an existing document using NSPersistentDocument, as part of initialization I'd like to prepare some content:

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

When I put this code in -init, the fetch request doesn't return any results.

I encountered this problem while refactoring the view-controller components from my NSPersistentDocument subclass to a new NSWindowController subclass. I used to handle this initialization in -windowControllerDidLoadNib:, but that isn't called anymore.

If I move the code from -init to -makeWindowControllers I get the results I expect. Is -makeWindowControllers really the right place to prepare content like this?


回答1:


Based on the responses I've gotten I think I'm doing the right thing, so here's my answer to my own question.

If you're using the Core Data stack provided by NSPersistentDocument, you can not use Core Data in -init.

Instead, you should:

  1. Put the document-initialization code directly in -windowControllerDidLoadNib: – or if you use a custom NSWindowController subclass, in -makeWindowControllers.
  2. You may also abstract the document-initialization code into a helper method with some unique name like -setUpDocument, and call that method from -makeWindowControllers/-windowControllerDidLoadNib: instead.

If you're using a plain NSDocument, or you're setting up the Core Data stack on your own, you can set up the document model in -init.




回答2:


From this question and your related question about NSArrayControllers, I'm gathering that you're doing something like this:

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

When you do this, -windowControllerDidLoadNib: won't be called, because the NSDocument object isn't the Nib's owner if you init that way. If you look at NSDocument.h you'll see the following comment (see added emphasis):

/* 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;

If you, instead, do this:

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

I believe you'll find that -windowControllerDidLoadNib: is called again. That may not help you, if you have a good reason for that Nib's owner to not be the NSDocument, but that's why -windowControllerDidLoadNib: isn't being called, and what you can do to get that behavior back. That's almost certainly a better place to be doing fetches than in init, which likely happens before all the necessary CoreData support stuff is in place. So that's one option.




回答3:


If the code is not called from init that is because your document is being initialized elsewhere such as initWithContentsOfURL:ofType:error:, initForURL:withContentsOfURL:ofType:error:, initWithType:error: or initWithCoder: makeWindowControllers is not for setting up your data. Try implementing all of the above initializers and log to see which is getting called.



来源:https://stackoverflow.com/questions/7734701/is-makewindowcontrollers-the-best-place-to-initialize-an-nspersistentdocument

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!