1

オブジェクトを作成し、myObjectある時点で通知を受け取るまでロックしたいとします。通知を受け取ったら、ロックを解除したいと思います。これは GCD を使用して達成できますか、それともロックなどを使用する必要がありますか? ありがとう!

編集:これが私が解決しようとしている正確な問題です。に写真を書き込んでいるスレッドがありますALAssetsLibrary。UI はALAssets、ライブラリから写真を表示するために使用しています。私の問題はこれです:writeImageDataToSavedPhotosAlbumライブラリを変更するとすべてALAssetsが無効になるため、2番目のスレッドがライブラリから写真をロードしている最中に失敗する可能性があります(多くの場合失敗します)。これを修正する唯一の方法は の後にロードすることだと読んだALAssetsLibraryChangedNotificationので、ライブラリに書き込んだ瞬間から通知を受け取る瞬間までライブラリにアクセスできないようにしようとしています。

4

1 に答える 1

0

キューの観点から問題を考えるべきなのに、ロックの観点から問題を考えています。あなたがしたいことは、いくつかの共有「リソース」が与えられた場合、このようなものです(テストされていません)。これはアプローチの単なるスケッチですが、正しい軌道に乗るはずです。可能な限りロックを避ける必要があります。

@implementation Resource

- (id)init {
...
  // Assuming you are the only one who can possibly change the library
  // See suspendQueue for related code
  [[NSNotificationCenter defaultCenter] addObserver:self 
                                          selector:@(resumeQueue:) ...
                                              name:...thenoteification...];

// Always request things synchronously on the queue
- (Something *)somethingForStuff:(Stuff *)stuff {
  __block Something *result;
  dispatch_sync(self.queue, ^{
    result = GetSomethingForStuffFromMe(stuff);
  });
  return result;
}

// Always change things asynchronously on the queue with a barrier
// And in your case, suspend the queue to lock it until done
- (void)setSomething:(Something *)something forStuff:(Stuff *)stuff {
  dispatch_barrier_async(self.queue, ^{
    SetSomethingForStuff(something, stuff);
    [self suspendQueue];
  });
}

// You'll need to think this through a little bit. It depends on your exact model.
// I'm using isSuspended really just as an error-check to make sure something
// hasn't gone wrong.
- (void)suspendQueue {
  NSAssert(! self.isSuspended, @"In this example, I don't allow recursive suspension.");
  [self.queue suspend];
  self.suspended = YES;
}

// This code assumes you're the only one who can cause this notification.
// You may need to change things a little if that's not true
- (void)resumeQueue {
  NSAssert(self.isSuspended, @"We should only ever see this notification if we caused it");
  self.suspended = NO;
  [self.queue resume];
}
于 2012-08-14T21:16:58.917 に答える