iOS使用GCD解锁通知对象

时间:2012-08-14 19:06:46

标签: ios notifications grand-central-dispatch

假设我创建了一个对象myObject,在某些时候我希望它被锁定,直到我收到通知。我收到通知后,我想解锁它。这可以使用GCD完成,还是必须使用锁或什么?谢谢!

编辑: 所以这是我正在努力解决的确切问题。 我有一个帖子正在向ALAssetsLibrary写照片。 用户界面正在使用ALAssets来显示图书馆中的照片。 我的问题是:writeImageDataToSavedPhotosAlbum更改了库,导致所有ALAssets无效,所以如果我的第二个线程正在从库中加载照片,它可能会失败(并且经常会)。我读到解决这个问题的唯一方法是在ALAssetsLibraryChangedNotification之后加载,所以我从写入它的那一刻起到收到通知的那一刻我都试图使库无法访问。

1 个答案:

答案 0 :(得分: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];
}