3

我有一个方法,someMethod当 a) 用户点击视图和 b) 当用户拖动视图时调用。在someMethod中,有一个UIView animateWithDuration块使视图顶部的工具栏消失,并相应地重置其框架。如果用户点击视图,而不是拖动它,someMethod将在动画仍在完成时触发,这不是我想要的行为(简单地取消动画不起作用,因为完成块仍然触发(即使我检查'完成' BOOL)。所有事情都在考虑之中,我只是不希望在动画仍在进行时触发此方法。

显然,一个简单的解决方案是使用 a 设置手动锁定,BOOL并且只允许在锁定空闲时调用该方法。

我想知道,有没有更优雅的方法来完成这个?可以使用 GCD 或其他一些库来实现这一点,所以它更简单吗?

更新:我确实尝试使用同步,但问题是该方法触发动画,完成,但动画仍在另一个线程上运行。还有其他想法吗?

4

4 回答 4

1

计时器用完并不意味着或需要辅助线程。您可以控制计时器安排在哪个线程上。如果您只是在主线程上安排计时器,那么这两件事都发生在主线程上。

使用的建议@synchronized实现了给定代码块没有同时为同一个对象(无论 的参数是什么@synchronized)运行的效果,但这与说它不在两个不同的线程上运行不同。

如果要检测是否在主线程以外的线程上调用了某个方法,然后将其分流到主线程,可以使用+[NSThread isMainThread]and dispatch_async(dispatch_get_main_queue(), ^{ /* re-call current method */ });

于 2012-06-09T08:43:36.483 回答
1

在现代 iOS 和 OS X 中,控制执行的最优雅的机制是使用调度队列和块。对于全局锁,您可以使用单个串行队列并同步或异步向它发出请求,具体取决于您是否希望在执行关键代码时停止该线程上的剩余执行。

在某处全局声明您的队列:

dispatch_queue_t myQueue;

因此,当您启动时,您将创建队列:

myQueue = dispatch_queue_create( "CRITICAL_SECTION", DISPATCH_QUEUE_SERIAL);    // FIFO

当您想要执行代码的关键部分时,您可以使用:

dispatch_sync( shpLockQueue, ^{
     // critical section here
});

根据您的需要,您可能希望在这些块之一中调用您的方法,或者您可能希望在您正在保护的对象中拥有该块。

如果您需要确保例程在主线程上运行,您可以为此使用主调度队列,但如果没有必要,使用您自己的队列会更有效。如果您选择使用主队列,则无需设置自己的队列或存储它,您只需在以下范围内执行代码:

dispatch_sync( dispatch_get_main_queue(), ^{
     // critical section here
});
于 2012-06-09T10:32:54.510 回答
0

我建议使用 @synchronized() 块,这里有一篇很棒的博客文章来解释它:

http://googlemac.blogspot.com/2006/10/synchronized-swimming.html

@synchronized(self) {
     [self someMethod];  
}
于 2012-06-09T08:39:03.507 回答
0

好吧,即使只使用一个全局变量,也不能保证互斥,因为变量在更新之前被复制到寄存器中,如果这确实是你所说的“手动锁定 BOOL ...”,不幸的是它们不是真正优雅的解决方案....查看https://developer.apple.com/library/mac/ipad/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html

祝你好运。

于 2012-06-09T08:42:00.163 回答