我正在实现一个通过用户输入动画的健康栏。
这些动画使其上升或下降一定量(比如 50 个单位),并且是按下按钮的结果。有两个按钮。增加和减少。
我想在健康栏上执行锁定,以便一次只有一个线程可以更改它。问题是我遇到了僵局。
我猜是因为一个单独的线程运行一个由另一个线程持有的锁。但是当动画完成时,那个锁就会让位。如何实现在 [UIView AnimateWithDuration] 完成时结束的锁?
我想知道是否NSConditionLock
可行,但如果可能的话,我想使用 NSLocks 以避免不必要的复杂性。你有什么建议吗?
(最终我想让动画“排队”,同时让用户输入继续,但现在我只想让锁工作,即使它首先阻止输入。)
(嗯,想想看,同一个 UIView 一次只有一个 [UIView AnimateWithDuration] 运行。第二个调用将中断第一个调用,导致完成处理程序立即为第一个运行。也许第二个锁在首先有机会解锁。在这种情况下处理锁定的最佳方法是什么?也许我应该重新访问 Grand Central Dispatch 但我想看看是否有更简单的方法。)
在 ViewController.h 我声明:
NSLock *_lock;
在 ViewController.m 我有:
在加载视图中:
_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;
}
}
输出:
复制说明:点击“减少”一次
触摸线程按钮1..
tryTheLock beforeLock .. 免费。
tryTheLock afterLock.. 锁定。开始动画块 - 值:250 结束动画块 - 值:250 - 完成:是
tryTheLock beforeUnlock .. 锁定。
tryTheLock afterUnlock .. 免费。
结论:这按预期工作。
--
输出:
重现说明:快速点击“减少”两次(中断初始动画)..
触摸线程按钮1..
tryTheLock beforeLock .. 免费。
tryTheLock afterLock.. 锁定。BEGIN animationBlock - val: 250 touchThreadButton1..
tryTheLock beforeLock.. 锁定。 * -[NSLock lock]: deadlock ( '(null)') * Break on _NSLockError() 进行调试。
结论。死锁错误。用户输入被冻结。