我正在實施一個通過用戶輸入進行動畫的健康欄。如何執行等待動畫完成的鎖定?
這些動畫使它上下一定量(比如50個單位),並且是按下按鈕的結果。有兩個按鈕。增加和減少。
我想在健康欄上執行鎖定,以便一次只有一個線程可以更改它。問題是我陷入了僵局。
我猜測是因爲一個單獨的線程運行由另一個線程持有的鎖。但是當動畫完成時,該鎖定會讓路。你如何實現在[UIView AnimateWithDuration]完成時結束的鎖定?
我在想如果NSConditionLock
是要走的路,但我想盡可能使用NSLocks以避免不必要的複雜性。你有什麼建議?
(最後我想有動畫「排隊」,同時讓用戶輸入繼續,但現在我只是想獲得鎖的工作,即使它阻止輸入第一。)
(HMM來想象一下,同一個UIView只有一個[UIView AnimateWithDuration]運行,第二個調用會中斷第一個,導致完成處理程序立即運行,也許第二個鎖在第一個運行之前有一個機會在這種情況下處理鎖定的最好辦法是什麼?或許我應該重訪Grand Central Dispatch,但我想看看是否有更簡單的方法。)
在ViewController.h中,我聲明:
NSLock *_lock;
在ViewController.m我有:
在的loadView:
_lock = [[NSLock alloc] init];
ViewController.m的剩餘部分(相關部分):
-(void)tryTheLockWithStr:(NSString *)str
{
LLog(@"\n");
LLog(@" tryTheLock %@..", str);
if ([_lock tryLock] == NO)
{
NSLog(@"LOCKED.");
}
else
{
NSLog(@"free.");
[_lock unlock];
}
}
// TOUCH DECREASE BUTTON
-(void)touchThreadButton1
{
LLog(@" touchThreadButton1..");
[self tryTheLockWithStr:@"beforeLock"];
[_lock lock];
[self tryTheLockWithStr:@"afterLock"];
int changeAmtInt = ((-1) * FILLBAR_CHANGE_AMT);
[self updateFillBar1Value:changeAmtInt];
[UIView animateWithDuration:1.0
delay:0.0
options:(UIViewAnimationOptionTransitionNone|UIViewAnimationOptionBeginFromCurrentState|UIViewAnimationOptionAllowUserInteraction)
animations:
^{
LLog(@" BEGIN animationBlock - val: %d", self.fillBar1Value)
self.fillBar1.frame = CGRectMake(FILLBAR_1_X_ORIGIN,FILLBAR_1_Y_ORIGIN, self.fillBar1Value,30);
}
completion:^(BOOL finished)
{
LLog(@" END animationBlock - val: %d - finished: %@", self.fillBar1Value, (finished ? @"YES" : @"NO"));
[self tryTheLockWithStr:@"beforeUnlock"];
[_lock unlock];
[self tryTheLockWithStr:@"afterUnlock"];
}
];
}
-(void)updateFillBar1Value:(int)changeAmt
{
self.prevFillBar1Value = self.fillBar1Value;
self.fillBar1Value += changeAmt;
if (self.fillBar1Value < FILLBAR_MIN_VALUE)
{
self.fillBar1Value = FILLBAR_MIN_VALUE;
}
else if (self.fillBar1Value > FILLBAR_MAX_VALUE)
{
self.fillBar1Value = FILLBAR_MAX_VALUE;
}
}
輸出:
重現的說明:點擊 「減少」 一旦
touchThreadButton1 ..
tryTheLock beforeLock .. 免費。
tryTheLock afterLock .. LOCKED。 BEGIN animationBlock - VAL:250 END animationBlock - VAL:250 - 完成:YES
tryTheLock beforeUnlock .. 鎖定。
tryTheLock afterUnlock .. 免費。
結論:這按預期工作。
-
輸出:
重現的說明:輕按 「降低」 快速兩次(中斷初始動畫)..
touchThreadButton1 ..
tryTheLock beforeLock .. 免費。
tryTheLock afterLock .. LOCKED。 BEGIN animationBlock - VAL:250 touchThreadButton1 ..
tryTheLock beforeLock .. 鎖定。 * - [NS鎖定鎖定]:死鎖('(null)') *中斷_NSLockError()以進行調試。
結論:死鎖錯誤。用戶輸入被凍結。
謝謝先生!我很欣賞你如何以清晰的方式展示NSOperationQueue。將大小操作封裝在自己的類中相當優雅。它完美的作品。 –
@BlackOrchid僅供參考,我相信你很久以前就已經過去了這個問題,但我用一種更簡單的方法對它進行了更新。 – Rob
希望我可以不止一次地對此讚賞。 :) –