Я реализую панель здоровья, которая анимируется с помощью пользовательского ввода.Как выполнить блокировку, ожидающую завершения анимации?
Эти анимации позволяют продвигаться вверх или вниз на определенную величину (например, 50 единиц) и являются результатом нажатия кнопки. Есть две кнопки. Увеличение и уменьшение.
Я хочу выполнить блокировку на панели состояния, чтобы только один поток мог изменить его за раз. Проблема в том, что я зашел в тупик.
Я предполагаю, что в отдельном потоке выполняется блокировка, удерживаемая другим потоком. Но эта блокировка уступит место, когда анимация завершится. Как реализовать блокировку, завершившуюся после завершения [UIView AnimateWithDuration]?
Интересно, может ли быть NSConditionLock
, но я хочу использовать NSLocks, если это возможно, чтобы избежать ненужной сложности. Что вы порекомендуете?
(В конце концов, я хочу, чтобы иметь анимации «очереди», позволяя пользовательский ввод продолжить, но сейчас я просто хочу, чтобы получить блокировку работать, даже если он блокирует вход первого.)
(Хмм приходят подумайте, что существует только один [UIView AnimateWithDuration], работающий одновременно для одного и того же UIView. Второй вызов прерывает первый, заставляя обработчик завершения запускаться сразу для первого. Может быть, второй замок работает до того, как первый имеет шанс чтобы разблокировать.Какой лучший способ справиться с блокировкой в этом случае? Возможно, мне стоит вернуться к 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;
}
}
Выход:
To-Воспроизведите Инструкции: Нажмите "Уменьшить" раз
touchThreadButton1 ..
tryTheLock beforeLock .. бесплатно.
tryTheLock последующийLock .. LOCKED. НАЧАТЬ animationBlock - Вэл: 250 END animationBlock - VAL: 250 - закончил: ДА
tryTheLock beforeUnlock .. LOCKED.
tryTheLock последующийUnlock .. свободный.
Заключение: Работает так, как ожидалось.
-
Выход:
To-Воспроизведите Инструкции: Нажмите "Уменьшить" дважды быстро (перебивает начальную анимацию) ..
touchThreadButton1 ..
tryTheLock передLock .. бесплатный.
tryTheLock последующийLock .. LOCKED. НАЧАТЬ animationBlock - VAL: 250 touchThreadButton1 ..
tryTheLock beforeLock .. LOCKED. * - [Блокировка NSLock]: тупик ('(null)') * Перерыв на _NSLockError() для отладки.
Заключение. Ошибка взаимоблокировки. Ввод пользователя заморожен.
Спасибо, сэр! Я ценю, как вы четко демонстрируете NSOperationQueue. Инкапсуляция операции размера в своем классе довольно изящна. Он работает отлично. –
@BlackOrchid FYI, я уверен, что вы давно прошли мимо этого вопроса, но я обновил его с помощью значительно более простого подхода. – Rob
Жаль, что я не мог это сделать. :) –