我正在实施一个通过用户输入进行动画的健康栏。如何执行等待动画完成的锁定?
这些动画使它上下一定量(比如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
希望我可以不止一次地对此赞赏。 :) –