2017-03-02 19 views
0

我需要一种“调度一次”机制,当满足所有条件时,比如说A & B是真实的,运行这部分代码一次,但只有一次。因此,如果以后再次满足所有条件(A & B再次为真,但我不在乎),代码将不会再运行。如何实现一个“dispatch_once”方法,不是为多线程环境,而是只在满足所有条件时运行一次

我不认为dispatch_once在这里很合适。这里没有数据同步问题,稍后所有的标准都可能再次满足。现在我尝试2种方法:

  1. KVO所有的标准,一旦满足,运行代码并停止KVO。
  2. 添加另一个属性,当满足一些条件时更新它。当满足所有条件时,运行代码,然后将其设置为特殊值,这将防止代码再次运行。例如,将其初始值设置为1,当A为真时& 2,当B为真时& 4,所以当它为7时,运行代码并将其值设置为0.然后,它将不会再次为7 。

那么有没有更好的方法?

---- ----更新

除了知道有多少种方法我能做到这一点,我也找了“系统性”的方式来做到这一点。现在,当A & B都是真的时,我需要运行第一部分;第2部分一旦出现C时,第3部分一旦E & F为真。我使用了我提到的两种方法。代码看起来很乱,而其他人很难理解我想要完成的事情。

回答

1

假设你想这是我看到的没有错,每个应用程序仅发生一次:

- (void)tryOnce{ 
    if (a && b){ 
     dispatch_once()... 
    } 
} 

你如何决定何时运行if完全到你的具体实施。在ab使用KVO似乎是恰当的,如果他们能在多个位置进行修改,或者您可以覆盖setter方法:

- (void)setA(id a) { 
    _a = a; 
    [self tryOnce]; 
} 
- (void)setB(id B) { 
    _b = b; 
    [self tryOnce]; 
} 

---编辑为OP的更新---

一个通用的解决方案将是创建一个包含两个块并覆盖observeValueForKeypath:...的类。这可以避免在你的(可能)UIViewController的observeValueForKeyPath中进行大量混乱的检查,并且在你发现自己处理同一方法的许多调用的任何地方(UITextView委托等等)通常都是一个很好的模式。

@implementation ObserveAndDoOnce 
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{ 
    if (!self.checkBlock || !self.finishedBlock){ return; } 
    if (self.checkBlock()) { // checkBlock returns a BOOL 
     self.finishedBlock(); 
     self.checkBlock = nil; 
     self.finishedBlock = nil; 
    } 
} 
@end 

ObserveAndDoOnce *a_and_b = [ObserveAndDoOnce new]; 
[self addObserver:a_and_b forKeyPath:keypath_for_a...]; 
[self addObserver:a_and_b forKeyPath:keypath_for_b...]; 
a_and_b.checkBlock = ... 
a_and_b.finishedBlock = ... 
+0

但是在使用dispatch_once时看不到附加值 – Qiulang

+0

这完全取决于您要完成的工作。 'dispatch_once'没有任何害处。如果你不喜欢它,你可以像'didTryOnce'一样添加一个属性或静态变量,然后执行'if(a && b &&!didTryOnce)...'。 'dispatch_once'每个应用程序运行最多只能运行一次** **有保证**而如果你使用'didTryOnce'路径,你可能会释​​放你的对象或者重置'didTryOnce'并因此让代码段运行稍后再试。 – arsenius

+0

更新了我关于我想要完成的问题。 – Qiulang

相关问题