是否有一种简单的方法(在Cocoa/iOS中)将方法调用排队,以便在下一个运行循环中运行一次



UIView有一个可以在同一个事件循环中调用多次的setNeedsDisplay方法,因为知道重绘工作很快就会发生,而且只有一次。

是否有这种行为的通用机制Cocoa?也就是说,你想把选择器排队多少次就排队多少次,当时间到了,选择器会运行一次;清除队列。"

我知道我可以在我的目标中用某种状态跟踪来做这个,或者用NSOperationQueue。我只是想知道是否有一种轻量级的方法我错过了。

(当然,答案可能是"不"。)

setNeedsDisplay不是您所描述的一个很好的例子,因为每次调用它时它实际上都在运行。它只是树立了一面旗帜。但是这个问题很好。

一个解决方案是使用NSNotificationQueue与NSNotificationCoalescingOnName

另一个解决方案是自己做一个蹦床来粘合。我没有一个很好的关于蹦床的博客参考,但这里有一个例子(ltrampoline)。如果你想在一段时间内合并这些信息,构建这个并不难。我曾经用类似的forwardInvocation:建造了一个蹦床:

- (void)forwardInvocation:(NSInvocation *)invocation {
  [invocation setTarget:self.target];
  [invocation retainArguments];
  [self.timer invalidate];
  self.timer = [NSTimer scheduledTimerWithTimeInterval:self.timeout invocation:invocation repeats:NO];
}

这实际上在一段时间内将所有消息合并到对象(而不仅仅是匹配消息)。这就是这个特殊问题所需要的。但是您可以在此基础上进行扩展,以跟踪正在合并的选择器,并检查调用以查看它们是否"充分匹配"。"

要在下一个事件循环中运行,只需将timeout设置为0。

我一直想写关于蹦床的博客。所需先令:我即将出版的书在第4章和第20章中介绍了蹦床。

[NSObject cancelPreviousPerformRequestsWithTarget:self 
                                         selector:@selector(doTheThing:)
                                           object:someObject];
[self performSelector:@selector(doTheThing:) 
           withObject:someObject 
           afterDelay:0];

这并不完全是UIView是如何做的,因为setNeedsDisplay只是设置一个标志和内部UIView机制确保在设置绘图环境后调用drawRect:,但这是一种通用的方式,不需要在你的类中进行任何特殊的状态跟踪。

相关内容

最新更新