我想对健康条执行锁定,以便只有一个线程可以同时更改它。问题是我遇到了死锁。
我猜测是因为另一个线程运行了由另一个线程持有的锁。但是当动画完成时,该锁将让位。如何实现在 [UIView animateWithDuration] 完成时结束锁定?
我想知道是否可以使用 NSLocks 来避免不必要的复杂性,但我不确定是否应该使用 NSConditionLock。你有什么建议吗?
(最终,我希望在让用户输入继续的同时“排队”播放动画,但现在我只想让锁起作用,即使它会先阻止输入。)
(嗯,想想看,对于同一个 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..
在锁定之前尝试锁定.. 空闲。
在锁定之后尝试锁定.. 已锁定。 开始动画块 - val: 250 结束动画块 - val: 250 - 完成: 是
在解锁之前尝试解锁.. 已锁定。
在解锁之后尝试解锁.. 空闲。
结论: 这符合预期。
--
输出:
重现步骤: 快速点击两次“减少”按钮(中断初始动画)..
touchThreadButton1..
在锁定之前尝试锁定.. 空闲。
在锁定之后尝试锁定.. 已锁定。 开始动画块 - val: 250 touchThreadButton1..
在锁定之前尝试锁定.. 已锁定。 * -[NSLock lock]: 死锁 ( '(null)') * 在 _NSLockError() 上打断点以进行调试。
结论. 死锁错误。用户输入被冻结。