@synchronized [UIView animationWithDuration ...]锁定结束?

时间:2014-03-05 13:08:53

标签: ios objective-c multithreading uikit

@synchronized会锁定直到动画结束吗?

__weak typeof(sharedManager) weakManager = sharedManager;

^(CMDeviceMotion *motion, NSError *error)         
{

@synchronized(weakManager)
             { ... some code
                 if (angle != sharedManager.angle)
                 {
                     if (sharedManager.isLocked) return;

                     sharedManager.locked = YES;

                     sharedManager.angle = angle;

                     CGAffineTransform transform = (angle == 0) ?
                     CGAffineTransformIdentity : CGAffineTransformMakeRotation(angle);
                     sharedManager.currentTransform = transform;

                     [UIView animateWithDuration:.25
                                      animations:^
                     {
                         [weakManager.animatedViews setValue:[NSValue valueWithCGAffineTransform:transform]
                                                      forKey:@"transform"];

                     }
                                      completion:^(BOOL finished)
                     {
                         weakManager.locked = NO;
                     }];
                 }
             }
}];

2 个答案:

答案 0 :(得分:2)

没有。它只会等待方法调用的持续时间。实际动画是异步发生的,不会影响锁定。

我想如果你想要这种行为,你可以使用NSRecursiveLock并在动画的完成块中显式解锁,但这是一件非常奇怪的事情。

答案 1 :(得分:1)

不,@synchronized在其块退出时释放其锁定,这是在动画开始之前。但是在任何情况下你几乎都不想再使用@synchronized了。这是一个非常昂贵的锁。

这段代码有点奇怪。如果经理目前正在动画,你真的想丢掉更新吗?你不想搬到新目标吗?这就是Core Animation正常运作的方式;你设定了一个目标,开始制作动画,如果事情发生了变化,你只需要为这个新目标制作动画。


如果您想序列化操作,这似乎是您的目标,那么更好的工具是NSOperation或调度队列。我可能在这里使用串行调度队列。将您想要的操作放在队列中(无论修改weakManager)。如果您在动画完成之前不想再处理任何操作,请调用dispatch_suspend暂停队列,并dispatch_resume在完成块中再次启动它。

此处另一个可能有用的工具是dispatch_sempahore,可用于代替isLocked属性。但我建议尽可能使用队列。在大多数情况下,如果你锁定了现代的Cocoa,你就会做错事。