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 (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