Re: NSDocument Serialization (-performSynchronousFileAccessUsingBlock: and friends)
Re: NSDocument Serialization (-performSynchronousFileAccessUsingBlock: and friends)
- Subject: Re: NSDocument Serialization (-performSynchronousFileAccessUsingBlock: and friends)
- From: Kevin Perry <email@hidden>
- Date: Thu, 29 Sep 2011 09:20:18 -0700
The header documentation for -performSynchronousFileAccessUsingBlock: (which also applies to performAsynchronousFileAccessUsingBlock:) says:
"this method's primary use is to wait for asynchronous saving, but in contrast with that method it is only for use to wait for the part of an asynchronous saving operation that actually touches the document's file or values in memory that are in some way relative to the document's file."
and:
"In general you should use this method or -performAsynchronousFileAccessUsingBlock: around code that gets or sets values in memory that only make sense in the context of the document file's current state."
In other words, these methods are used to prevent multiple operations from operating simultaneously on the document's file and the file-related ivars. In order to accomplish this, asynchronous saving must be implemented like so (simplified, obviously):
performAsynchronousFileAccessUsingBlock:^(fileAccessCompletionHandler) {
dispatch_async(^{
write();
continueAsynchronousWorkOnMainThreadUsingBlock:^{
handle error, or update file ivars (fileURL, fileModificationDate, fileType, change count, etc.)
fileAccessCompletionHandler();
}
})
}
waitForUserInteractionUnblocking()
If it were to call the fileAccessCompletionHandler any earlier then it might be possible, for example, for -fileModificationDate to be invoked on the main thread after -writeSafelyToURL: has written the file, but before the value has been properly updated.
To address the example in your previous email, you want to do the latter option, where you protect both -fileURL and the actual operation on the result in a single call to -perform(A)synchronousFileAccessUsingBlock:. That is the only way to ensure that something else within the process (or something in another process using File Coordination) doesn't move the file out from under you before you get to invoke -moveItemAtURL:toURL:error: or try to write to the old URL before your move is complete, etc.
I don't see the nested uses of performSynchronousFileAccessUsingBlock: you mentioned in that code, but that's not a problem anyway, since file access is recursive, as long as it happens synchronously within the outer-most file access block (a fact that admittedly may not be documented well anywhere).
-KP
On Sep 28, 2011, at 11:23 PM, Kyle Sluder wrote:
> On Wed, Sep 28, 2011 at 10:55 PM, Kyle Sluder <email@hidden> wrote:
>> I'd really appreciate if the documentation spelled out exactly how
>> NSDocument uses these methods.
>
> To give an example of a specific NSDocument usage that I'd like to
> know about: how does asynchronous saving use
> -performAsynchronousFileAccessUsingBlock:? I'm envisioning something
> like this:
>
> - (void)saveToURL:(NSURL *)url ofType:(NSString *)type
> forSaveOperation:(NSSaveOperation)op completionHandler:(void
> (^)(NSError *errorOrNil))completionHandler {
> id saveToken = [self changeCountTokenForSaveOperation:op];
>
> if ([self canAsynchronouslyWriteToURL:url ofType:type forSaveOperation:op]) {
> [self performAsynchronousFileAccessUsingBlock:(void
> (^fileAccessCompletionHandler)(void)) {
> dispatch_async(backgroundQueue, ^{
> NSError *error;
> BOOL success;
> success = [self writeSafelyToURL:url ofType:type
> forSaveOperation:op error:&error];
>
> fileAccessCompletionHandler();
>
> if (success)
> [self continueAsynchronousWorkOnMainThreadUsingBlock:^{
> [self setFileURL:url];
> [self setFileModificationDate:[NSDate date]];
> [self setFileType:type];
> [self setAutosavedContentsFileURL:url];
> [self updateChangeCountWithToken:token forSaveOperation:op];
> completionHandler(nil);
> }];
> else
> [self continueAsynchronousWorkOnMainThreadUsingBlock:^{
> completionHandler(error);
> }];
> });
>
> WaitForUnblockUserInteraction();
> }];
> }
> }
>
> Am I on the right track here?
>
> --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
_______________________________________________
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