Re: How to run a panel that customizes a new NSDocument
Re: How to run a panel that customizes a new NSDocument
- Subject: Re: How to run a panel that customizes a new NSDocument
- From: Ben Haller <email@hidden>
- Date: Thu, 22 Oct 2009 09:27:03 -0400
On 22-Oct-09, at 2:24 AM, Quincey Morris wrote:
1. Yes, there's a defect in the NSDocumentController design which
makes it awkward to pass an initial state to a new document without
having to re-implement everything that NSDocumentController does.
Awkward but not impossible or even difficult. So let's just get over
it and move on.
Now that I've heard someone knowledgeable say that, I am happy to
move on. I figured I was just using the framework incorrectly, since
usually "fighting with the framework" indicates that (which indicates
how good Apple's designs usually are!)
2. My second suggestion *in no way* depends on knowing what any
method of NSDocumentController actually does, except that I
consulted the documentation for 'newDocument:' to guide me in
choosing which method to override. If that bugs you, override
'newDocument:' too, to make it do what the documentation says it
currently does, and you're future-proofed until and unless
'openUntitledDocumentAndDisplay:error:' is deprecated.
Given that they deprecated a wave of these methods in 10.4
(including the predecessor to openUntitledDocumentAndDisplay:error:),
that does worry me a bit. The architecture seems like a work in
progress, which makes me feel I ought to tread especially carefully.
My first suggestion depends on knowing that the type passed to the
new document instance will be provided by 'defaultType'. It's
conceivable but extremely unlikely that this is ever going to
change, but if that bothers you, use the second suggestion.
Both your fixes still strike me as hacks, and having just spent
some weekends updating old apps that were bitten by changes that I
thought at the time were "conceivable but extremely unlikely," I am
now more wary of such evaluations than I used to be. But your
suggestions do seem fairly safe.
Your existing code is, in a sense, more dependent on the current
implementation details of NSDocumentController, because you're
trying to do what the documentation says that NSDocumentController
does.
Yes, this is exactly what bothers me about it, and is why I've been
looking for a better solution.
3. The only ways my second suggestion (and, for all practical
purposes, my first suggestion) could fail are (a) if documents were
being created on multiple threads, which can't happen because
NSDocumentController isn't thread safe, or (b) if
'openUntitledDocumentAndDisplay:error:' could possibly get called
recursively, which it doesn't. If you're worried about that, then go
ahead and use your current implementation, which is perfectly viable
even if it makes you uncomfortable.
Well, I was worried about a scenario, for example, where multiple
documents were getting created at once, and that was done in an
interleaved fashion such that your suggested code would end up setting
the type into the special ivar/global multiple times, then getting the
last set type out of the ivar/global multiple times, thus making many
documents of the last type set, rather than one document each of each
one type set. But the more I ponder it the less likely that seems to
actually happen, so I won't worry about it.
Huh? You *are* getting advice from somebody who knows how this
architecture is intended to be used, both from having implemented "a
document like this", and from having carefully absorbed *extensive*
discussions on this list of how the NSError** output parameter is
intended to be used.
Please don't be so easily offended. Your original reply did not
indicate you had ever implemented such a scheme; it sounded like a
tossed-off guess. Your wording "I don't understand why you think you
can't..." made it sound like you felt there was no particular problem
with the design of the framework, which made me suspicious of your
answer; you seemed to just be saying "Why is there a problem, it's
easy to hack your way around it," which is an attitude that is not
terribly helpful when trying to understand the design of a framework
and how best to use it. Your acknowledgement in this reply that there
is indeed a defect in the architecture is much more useful.
Your answer to the NSError question ("you're not returning an error
object when you return nil at the end of the method") was unhelpful
since adding a return of an NSError just changed the behavior of the
code to a different, equally incorrect behavior; it took a more useful
tip from a different poster to point me to the fact that a
*particular* NSError needed to be returned, which was not mentioned in
any of the documentation that I was looking at. I state these things
not to be critical (not trying to start a flamewar here!), but to
explain to you why I asked the list for advice from "somebody who
knows how this architecture was intended to be used" and someone who
"has actually implemented a document like this". So. Thanks for your
replies, and I hope I've caused no lasting offense.
Read this:
http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/ErrorHandlingCocoa/CreateCustomizeNSError/CreateCustomizeNSError.html#/
/apple_ref/doc/uid/TP40001806-CH204-BAJIIGCC
and note particularly:
Note: Cocoa methods that indirectly return error objects in the
Cocoa error domain are guaranteed to return such objects if the
method indicates failure by directly returning nil or NO. With such
methods, you should always check if the return value is nil or NO
before attempting to do anything with the NSError object.
NSDocumentController methods play by these specific rules, so your
overrides must do so too. Returning the "user cancelled" error is a
special-case refinement of the technique that permits the (ultimate)
suppression of the error alert. (The same technique is useful in
cases where there really is an error but you want to display the
alert yourself, but you want to prevent the NSDocumentController
from complaining a second time.) It's not really well documented,
but -- I hope you noticed -- you got the answer for free just by
asking the question.
OK, very good to know. As I noted in an earlier post, I was misled
by the NSError documentation that says:
In general, a method should signal an error condition by—for example—
returning NO or nil rather than by the simple presence of an error
object. The method can then optionally return an NSError object by
reference, in order to further describe the error.
Thanks for the ref to the better doc; I will read that, and if it
seems appropriate, will file a doc bug on the item that misled me.
As for "I hope you noticed -- you got the answer for free just by
asking the question", yes, of course I appreciate the list's
helpfulness, and your helpfulness specifically, and I think I'm
careful to thank people. There's no need to be snippy. I've posted
hundreds of replies to this list and other cocoa-related lists helping
people out myself, although that was many years ago now, since I took
a multi-year break from coding recently. I'm sure there are old-
timers around who remember me.
So, thank you for your help. Let's move on.
Ben Haller
Stick Software
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden