Re: NSDocument Deferred loading
Re: NSDocument Deferred loading
- Subject: Re: NSDocument Deferred loading
- From: "Louis C. Sacha" <email@hidden>
- Date: Tue, 9 Mar 2004 15:08:27 -0800
Hello...
First, a warning from personal experience: the
NSDocumentController/NSDocument architecture has it's share of
problems in situations where the document needs to make certain types
of decisions. If you _really_ want to make everything work "the right
way", you will most likely end up rewriting a significant part of
NSDocumentController's functionality. Also, there are a number of
areas where the documentation for NSDocumentController and NSDocument
is significantly out of sync with reality, and I haven't had time to
finish filing bugs for all of them yet...
Second, you mentioned that you have this problem when using the
"Open Recent" menu to open files, but you will probably also have the
same problem if a file is opened using "Open..." and the open file
dialog. In general, there is no clear decision about what part of the
document architecture is supposed to show the failure alert, and the
NSDocumentController shows an alert in some cases but not others,
which results in the double alert problem if the document raises an
alert (and if the document does not raise an alert, a "no failure
alert" problem in other situations).
As far as where to put the parsing/dialog code, there are situations
where showWindows will not be called. It is possible to open a
document without it actually being displayed, and even if there isn't
any situation where you would do this yourself, it could still
happen. For example, in 10.3 (if I remember correctly) there was a
change made that causes documents printed from the Finder to always
be displayed in their application, but in earlier versions the
documents would be printed by the application without displaying the
document's windows.
I would recommed that you keep the parsing/dialog code in your
loadDataRepresentation:ofType: implementation to ensure that it is
always run, no matter how the document is opened. As you have found,
you can return TRUE/YES from loadDataRepresentation:ofType: to
prevent the controller from raising its error alert, although you do
still have to deal with the issue of closing the document. Using the
NSDocument instance method close instead of release should take care
of cleaning up references to the document that exist in the document
controller.
Placing a check in showWindows (using a instance variable BOOL or
some other flag) will take care of it most of the time.
- (void)showWindows
{
if (yourFlagThatIndicatesThatLoadingActuallyFailed) {[self close];}
else {[super showWindows];}
}
That still leaves the situations where the document is opened but not
displayed. I had also added a check to the document printing code,
similar to the following:
- (void)printShowingPrintPanel:(BOOL)flag
{
if (yourFlagThatIndicatesThatLoadingActuallyFailed) {[self close];}
else
{
/* ... code to print document here ... */
}
}
There are still a few problems with doing it this way, and there may
be other more significant problems that I didn't run into.
1) Documents will always be added to the list for "Recent Documents",
even if they can't be opened or the user cancels the process.
2) This approach will leak documents that are opened without being
displayed or printed (which, as far as I tested this approach, would
only be caused by applescripts or if you called the
NSDocumentController openDocumentWithContentsOf___:display: or
openUnititledDocumentofType:display: methods yourself with a display
argument of FALSE). You could add a timer to cover this case, if
there is some reason why others might want to use applescript to open
documents in your application without displaying them or if you might
need to do it in your own code.
3) Now that printing the document from the Finder in 10.3 causes the
document to be displayed before printing, this type of solution may
no longer work correctly in that situation, so you would want to make
sure to test that in 10.3 if your application supports printing. If
it doesn't work anymore when printing from the Finder, you might be
able to work around the issue by using [self
performSelector:@selector(close) withObject:nil afterDelay:0.1]
instead of [self close].
It's also possible that you could fix issues 2 and 3 by overriding
some of the NSApplication delegate methods (specifically
application:openFileWithoutUI: for #2 and application:printFile: for
#3) and doing some sort of check there... There were a number of
other issues where I was fighting the original implementation of
NSDocumentController, so I decided to take the path of rewriting most
of NSDocumentController instead :)
Hopefully some of this helps,
Louis
This brings me to my questions:
a. Where should I put the parsing/dialog code? (I'm think about
doing it in showWindows:)
b. What's the best way to close the document immediately? (I thought
about [self release] but I'm worried this could cause problems if
the showWindows caller tries to call any method after that)
Thanks!
Eyal Redler
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.