NSDocument Serialization (-performSynchronousFileAccessUsingBlock: and friends)
NSDocument Serialization (-performSynchronousFileAccessUsingBlock: and friends)
- Subject: NSDocument Serialization (-performSynchronousFileAccessUsingBlock: and friends)
- From: Kyle Sluder <email@hidden>
- Date: Wed, 28 Sep 2011 22:55:01 -0700
I'm working on a document-based application, and am a bit befuddled by
-performSynchronousFileAccessUsingBlock:. The documentation says that
"NSDocument itself consistently uses this mechanism around invocations
of the following methods:" and lists methods including -fileType,
-fileURL, etc. The documentation for
-performAsynchronousFileAccessUsingBlock: says
"saveToURL:ofType:forSaveOperation:completionHandler: uses this method
instead of performSynchronousFileAccessUsingBlock:," but doesn't
explain _how_ it uses it.
So what's the appropriate pattern if I need to make a decision based
on the return value of one of these methods, and potentially
manipulate the file to do so?
Is the following safe?
/**
* Please forgive the terrible abuse of path- and URL-based APIs here.
* This isn't a good example of how to deal with files. I'm more concerned
* with exploring the serialization patterns.
**/
- (BOOL)isInHomeDirectory {
__block NSURL *fileURL;
[self performSynchronousFileAccessUsingBlock:^{
fileURL = [self fileURL];
}];
return [[fileURL absoluteString] hasPrefix:NSHomeDirectory()];
}
- (IBAction)doThing:(id)sender {
BOOL isInHome = [self isInHomeDirectory];
[self performActivityWithSynchronousWaiting:YES usingBlock:^{
// Async operations might've moved us
if (isInHome && [self isInHomeDirectory]) {
__block NSURL *fileURL;
[self performSynchronousFileAccessUsingBlock:^{
fileURL = [self fileURL];
}];
NSURL destinationURL = [NSURL
fileURLWithPath:[NSTemporaryDirectory()
stringByAppendingPathComponent:[fileURL lastPathComponent]]];
NSError *error;
BOOL success = [[NSFileManager defaultManager]
moveItemAtURL:fileURL toURL:destinationURL error:&error];
if (!success)
[self presentError:error];
}
}];
}
//-----END-----//
I'm getting the impression that my use of
-performSynchronousFileAccess… around the minimal calls to -fileURL is
not safe. But you can't call -performActivityWithSynchronousWaiting:…
within the block passed to -performSynchronousFileAccess…. So I don't
know what to do. Should I move my call to -performActivity… as high up
as possible? Do I need to wrap my call to -[NSFileManager
moveItemAtURL:toURL:error:] in another call to
-performSynchronousFileAccess…? Can I nest calls to
-performSynchronousFileAccess…, or will that deadlock?
The following seems like it could be more correct, but it nests calls
to -performSynchronousFileAccess… and it seems to do a whole lot
within that synchronous block. Will that block other apps that are
waiting to perform coordinated reads and writes on that file?
/**
* Again, not meant to be a good example of using NSFileManager.
**/
- (BOOL)isInHomeDirectory {
// Must be called within a block passed to
-perform(A)SynchronousFileAccessUsingBlock:
NSURL *fileURL = [self fileURL];
return [[fileURL absoluteString] hasPrefix:NSHomeDirectory()];
}
- (IBAction)doThing:(id)sender {
[self performActivityWithSynchronousWaiting:YES usingBlock:^{
[self performSynchronousFileAccessUsingBlock:^{
BOOL isInHome = [self isInHomeDirectory];
if (isInHome) {
NSURL *fileURL = [self fileURL];
NSURL destinationURL = [NSURL
fileURLWithPath:[NSTemporaryDirectory()
stringByAppendingPathComponent:[fileURL lastPathComponent]]];
NSError *error;
BOOL success = [[NSFileManager defaultManager]
moveItemAtURL:fileURL toURL:destinationURL error:&error];
if (!success)
[self presentError:error];
}
}];
}
I'd really appreciate if the documentation spelled out exactly how
NSDocument uses these methods.
--Kyle Sluder
_______________________________________________
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