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 <kyle.slu...@gmail.com> 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 (Cocoa-dev@lists.apple.com)
> 
> 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:
> http://lists.apple.com/mailman/options/cocoa-dev/kperry%40apple.com
> 
> This email sent to kpe...@apple.com

_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to