对每个对象而不对每个类使用dispatch_once_t [英] Using dispatch_once_t per object and not per class

查看:127
本文介绍了对每个对象而不对每个类使用dispatch_once_t的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有多个调用特定方法的资源,但我想确保(每个对象)仅被调用一次

There are multiple sources calling a particular method, but I would like to ensure that it is called exactly once (per object)

我想使用类似的语法

// method called possibly from multiple places (threads)
-(void)finish
{

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [self _finishOnce]; // should happen once per object
    });
}
// should only happen once per object
-(void)_finishOnce{...}

问题是令牌在同一个类的所有实例之间共享-所以不是一个很好的解决方案-每个对象是否都有一个dispatch_once_t-如果不是,确保它被调用一次的最佳方法是什么?

Problem is the token is shared accross all instances of the same class - so not a good solution - is there a dispatch_once_t per object - if not what is the best way to ensure it is called once?

这是我正在考虑的提议解决方案-看起来还好吗?

Here is a proposed solution I am thinking of - does it seem alright?

@interface MyClass;

@property (nonatomic,strong) dispatch_queue_t dispatchOnceSerialQueue; // a serial queue for ordering of query to a ivar

@property (nonatomic) BOOL didRunExactlyOnceToken;

@end

@implementation MyClass

-(void)runExactlyOnceMethod
{
  __block BOOL didAlreadyRun = NO;
  dispatch_sync(self.dispatchOnceSerialQueue, ^{
     didAlreadyRun = _didRunExactlyOnceToken;
     if (_didRunExactlyOnceToken == NO) {
        _didRunExactlyOnceToken = YES;
     }
  });
  if (didAlreadyRun == YES)
  {
    return;
  }
  // do some work once
}

推荐答案

Avner,您可能很遗憾现在才问到;-)

Avner, you're probably regretting you asked by now ;-)

关于对问题的编辑,并考虑到其他问题,您或多或少地重新创建了老派"方式,也许这正是您应该做的(直接输入代码,请输入错字):

Regarding your edit to the question, and taking into account other issues, you've more-or-less recreated the "old school" way of doing this, and maybe that is just what you should do (code typed in directly, expect typos):

@implemention RACDisposable
{
   BOOL ranExactlyOnceMethod;
}

- (id) init
{
   ...
   ranExactlyOnceMethod = NO;
   ...
}

- (void) runExactlyOnceMethod
{
   @synchronized(self)     // lock
   {
      if (!ranExactlyOnceMethod) // not run yet?
      {
          // do stuff once
          ranExactlyOnceMethod = YES;
      }
   }
}

对此有一个通用的优化,但是在其他讨论之后,让我们跳过这一点.

There is a common optimization to this, but given the other discussion let's skip that.

这是便宜"吗?可能不是,但是所有事情都是相对的,它的花费可能并不大-但是YMMV!

Is this "cheap"? Well probably not, but all things are relative, its expense is probably not significant - but YMMV!

HTH

这篇关于对每个对象而不对每个类使用dispatch_once_t的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆