[SOLVED] How to save a document without blocking the main thread
[SOLVED] How to save a document without blocking the main thread
- Subject: [SOLVED] How to save a document without blocking the main thread
- From: Antonio Nunes <email@hidden>
- Date: Fri, 21 Dec 2007 02:40:32 +0000
On Dec 20, 2007, at 3:05 PM, Jean-Daniel Dupas wrote:
I don't know if it may solve your problem, but have a look at
"Message Flow in the Document Architecture"
http://developer.apple.com/documentation/Cocoa/Conceptual/Documents/Articles/ObjectInteractions.html
It show you in details what NSDocument do when it save a document.
Thanks Jean-Daniel, third time is lucky indeed, that was just the
pointer I needed. I had missed this in the docs, and it provides
enough details to sort things out. It's a bit late (or very early in
the morning if you like), so my head is not at its best and I'll have
to reverify after my sanity-nap, but it looks like I got it to work.
This is the new strategy:
I let the flow run normally up until
saveToURL:ofType:forSaveOperation:delegate:didSaveSelector:contextInfo
: which I override so that I can fork a thread at that point. At this
moment the URL still points to the real target directory (which it
won't after the writeSafelyToURL:ofType:forSaveOperation: method). I
pack whatever data I need into a dictionary and pass it as the object
to the thread.
The thread entry method unpacks the information in the dictionary and
uses that to resume the chain of commands by calling
saveToURL:ofType:forSaveOperation:error: the data is now saved in
writeToURL:ofType:error: which eventually gets called
When the flow of commands returns to the thread entry method there is
some minor clean up to do: if the saving was unsuccessful we need to
alert the user. If successful and this was an untitled document we
want to add it to the recent documents menu. This I still need to
figure out since the simple call [[NSDocumentController
sharedDocumentController] noteNewRecentDocument:self] doesn't seem to
work here.
In code:
// Hook into the flow to fork a thread
- (BOOL)saveToURL:(NSURL *)absoluteURL ofType:(NSString *)typeName
forSaveOperation:(NSSaveOperationType)saveOperation delegate:
(id)delegate didSaveSelector:(SEL)didSaveSelector contextInfo:(void
*)contextInfo
{
[NSApplication detachDrawingThread:@selector(saveDocumentToDisk:)
toTarget:self withObject:[NSDictionary
dictionaryWithObjectsAndKeys:absoluteURL, @"absoluteURL", typeName,
@"typeName", [NSNumber numberWithInteger:saveOperation],
@"saveOperation", nil]];
// Pretend everything is hunky-dory. If errors occur they will be
handled.
return YES;
}
// Thread entry:
- (void)saveDocumentToDisk:(NSDictionary *)info
{
NSURL *absoluteURL = [info objectForKey:@"absoluteURL"];
NSString *typeName = [info objectForKey:@"typeName"];
NSSaveOperationType saveOperation = [[info
objectForKey:@"saveOperation"] integerValue];
NSError *error;
BOOL success = [self saveToURL:absoluteURL ofType:typeName
forSaveOperation:saveOperation error:&error];
if ( ! success) {
// TODO: Alert user of failure to save.
} else {
// TODO: Add the document to the recent documents menu if it's not
already there
}
}
// Write out the data:
- (BOOL)writeToURL:(NSURL *)absoluteURL ofType:(NSString *)typeName
error:(NSError **)outError
{
// Assume success
BOOL success = YES;
[...lots of code to save document data...]
return success;
}
Cheers,
António
-----------------------------------------------------------
And could you keep your heart in wonder
at the daily miracles of your life,
your pain would not seem less wondrous
than your joy.
--Kahlil Gibran
-----------------------------------------------------------
_______________________________________________
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