Re: NSDocument newbie
Re: NSDocument newbie
- Subject: Re: NSDocument newbie
- From: James Bucanek <email@hidden>
- Date: Mon, 25 Jul 2005 22:58:32 -0700
John Stiles wrote on Monday, July 25, 2005:
>I just started putting together an app that would benefit greatly
>from supporting multiple windows open at once, so naturally I figured
>it should be based on NSDocument. (I also looked at
>NSWindowController's documentation but frankly I didn't understand
>it.) Anyway, my app is meant to open archives, not documents. An easy
>way to visualize it would be, imagine a tool that would let you
>browse inside ZIP files. My app isn't exactly the same, but for the
>purposes of this discussion, it's pretty much the same thing.
I have an app that does something very similar. "Opening" a document just opens a window into an existing database. The NSDocument doesn't contain the data in the document, and I don't "save" the data to the document.
>Now it appears that NSDocument's Open/Save functionality is all based
>around serializing the entire contents of the file into an NSData*.
>That isn't going to fly for my app... these archives can get very
>large (1GB+), they're never really read into memory all at once per
>se, and they're managed by a non-Cocoa-based library anyway. And
>realistically, there's never a time when you'd want to open an
>archive then use "Save As" to clone it. The typical usage pattern is
>going to be "open an archive, browse it, extract or insert a file,
>then close the archive." Or potentially "open two archives, move a
>file from archive A to archive B, then close them." Stuff along those
>lines.0
You want to go one level deeper than the NSData stuff that's provided and override the following methods:
- (BOOL)readFromFile:(NSString*)filename ofType:(NSString*)docType
- (BOOL)writeToFile:(NSString*)filename ofType:(NSString*)docType
- (void)close
Replace them with code that opens and closes your archive/whatever. My readFromFile method simply connects to the database. My writeToFile method does nothing (but return YES) because I never "write" the document. Close your file in the close method.
I also provide implementations of
- (BOOL)readFromURL:(NSURL*)url ofType:(NSString*)type
- (BOOL)writeToURL:(NSURL*)url ofType:(NSString*)type
which simply call readFromFile and writeToFile. I don't know if this is necessary, but it lets me sleep at night.
>So I realized that, even though the Open/Save/Revert/Undo
>functionality seems worthless for me, I can still get a lot of
>mileage out of just the "new document/close document" functionality.
>Without needing to write a lot of extra code, NSDocument can
>instantiate multiple copies of my nib, and then I can pop an
>NSOpenPanel sheet up right away as soon as the nib is instantiated,
>to let the user pick an archive. Then when I get a dealloc event I
>simply free all my data and close the archive. It seems pretty slick,
>actually. I mocked up a bit of the functionality this evening and
>made a lot of headway.
Don't try to do your own open dialog. Let NSDocumentController do this all for you. Register the document types with launch services, and NSDocumentController will put up the open dialog for you when the user uses File > Open.... The user selects a file *then* NSDocument gets created and readFromFile is called.
For my app, I also need to create a file when a "new" document window is created. If you do too, then you'll need to write your own newDocument handler that displays a Save dialog, creates the file, then sends the shared NSDocumentController openDocumentWithContentsOfFile:display:.
>I was just wondering if this was the right way to go, since it's so
>different from every tutorial and "Learn to Use Cocoa in 10 Days"
>explanation of how NSDocument works. Is there a smarter way to do it
>that I've overlooked? Is this a really useful solution or a dead end?
Read a little deeper into NSDocument and readFromFile. Basically, there are several different levels at which you can intercept the open/read/write/save document logic depending on if you have a traditional document, a package, or something completely different.
>Also, I have a quick techie question--I am trying to put an
>NSOpenPanel sheet on the window as soon as the user opens it, so they
>can select an archive. I found that -windowControllerDidLoadNib: is
>too soon, because the window isn't showing yet. Instead I set a
>temporary window delegate inside -windowControllerDidLoadNib: and use
>that delegate to drop the sheet as soon as the window gets its -
>windowDidBecomeKey: message. That works OK, but the sheet actually
>drops down before the window paints itself! Instead, I see the sheet
>drop down from an empty white box, and then as soon as it finishes
>animating, the Aqua window frame is rendered. Is there a smarter way
>to do this? I could set an NSTimer from inside the delegate that
>fired in one millisecond, and I'm sure that would give the event loop
>a chance to catch its breath, but is there a less convoluted way?
NSObject performSelector:withObject:afterDelay is the method you're looking for. But don't worry about it. I think you need to throw all of your open dialog code away anyway.
James
--
James Bucanek <mailto:email@hidden>
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden