• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
NSDocument Serialization (-performSynchronousFileAccessUsingBlock: and friends)
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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

  • Follow-Ups:
    • Re: NSDocument Serialization (-performSynchronousFileAccessUsingBlock: and friends)
      • From: Kyle Sluder <email@hidden>
  • Prev by Date: Daemon safe SMTP frameworks
  • Next by Date: Re: Daemon safe SMTP frameworks
  • Previous by thread: Re: Daemon safe SMTP frameworks
  • Next by thread: Re: NSDocument Serialization (-performSynchronousFileAccessUsingBlock: and friends)
  • Index(es):
    • Date
    • Thread