2014-03-05 65 views
0

請問@synchronized鎖直到動畫結束?@synchronized [UIView animationWithDuration ...]鎖定結束?

__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

號將只能等待方法調用的持續時間。實際動畫是異步發生的,不會影響鎖定。

我想如果你想要這樣的行爲,你可以使用NSRecursiveLock,並在動畫的完成塊中顯式解鎖,但這是一件很奇怪的事情。

+0

感謝您的回答 –

1

不,@synchronized在塊退出時釋放它的鎖,這是動畫開始之前。但是在任何情況下,你幾乎都不想再使用@synchronized。這是一個非常昂貴的鎖。

這段代碼有點奇怪。如果經理目前正在進行動畫製作,你是否真的想放棄更新?你不想移動到新的目標嗎?這就是Core Animation通常的工作原理;你設定了一個目標,開始製作動畫,如果事情發生了變化,你只需要爲這個新目標製作動畫。


如果你想序列操作,這似乎是你的目標,那麼,更好的工具是NSOperation或調度隊列。我可能會在這裏使用一個串行調度隊列。把你想要的動作放在隊列上(不管修改weakManager)。如果您不想在動畫完成之前執行更多操作,則請致電dispatch_suspend暫停隊列,然後撥打dispatch_resume以在完成塊中再次啓動它。

另一個可能有用的工具是dispatch_sempahore,它可以用來代替isLocked屬性。但如果可能的話,我建議只使用一個隊列。在大多數情況下,如果你正在鎖定現代可可,那麼你做錯了什麼。

+0

實際上,synchronized是爲了保護animatedViews在轉換過程中不被訪問,而一個對象可能會被取出。這個塊每秒被調用兩次,之後沒有其他任何事情。我猜這沒關係。是的,如果它是動畫,我想拋出更新。 Thx爲您的答案btw –

+0

我想在dispatch_asycn手動強制在同一個線程上的代碼。在此之前我實際上從未使用@synchronized。 –

+0

不要認爲這是「在同一線程上」。這可能會也可能不會是真實的。重點是它將被隊列序列化。 –