2010-10-28 55 views
4

Я использую базовый API-интерфейс блока для своих анимаций на iOS.Запуск блока анимации UIView, когда начинается другая анимация

Одна анимация имеет блок завершения и этот блок вызывается в конце анимации, приятно.

Однако, эта анимация может быть запущена несколько раз, когда пользователь прокручивает (анимация находится на UITableViewCell). Когда это происходит, блок завершения вызывается несколько раз. Параметр finished блока всегда равен YES.

Поскольку анимация на самом деле не закончена (произошла другая анимация), я думал, что параметр finished будет НЕТ, но это не так.

Я что-то пропустил? Как я могу избежать повторного вызова блока завершения?

+0

Вы делаете это сейчас в Симуляторе или пытаетесь запустить его на самом устройстве? Запуск анимации в UITableViewCells при прокрутке не похоже на то, что нужно сделать. Какова частота кадров при прокрутке? – runmad

+0

У меня также есть аналогичные проблемы. – karim

ответ

0

Я решил эту проблему, посмотрев, является ли блок завершения релевантным в начале этого блока.

Параметр finished не имеет значения прямо сейчас. Я общался с Apple, и они сказали мне, что это исправлено в iOS 4.2.

+0

Я использую ios5, и, похоже, проблема все еще не решена. Когда вы говорите: «Я разрешил эту проблему, посмотрев, является ли блок завершения релевантным в начале этого блока», можете ли вы объяснить, что вы подразумеваете под этим? –

+0

Я согласен, что не кажется, что параметр 'finished' работает правильно. Я получил желаемое поведение, добавив «animCount» ivar, который я увеличиваю/уменьшаю, когда анимация начинается и заканчивается. Я использую только код блока завершения, если это '0'. – zekel

5

Блок завершения называется несколько раз просто потому, что в вашем случае ваша анимация запускается несколько раз. Что происходит, так это то, что iOS вызывает ваш блок анимации каждый раз, когда ему говорят так, вероятно, в отдельном потоке. Затем для каждой анимации он отслеживает свое завершение, а по завершении вызывает соответствующий блок завершения. Таким образом, вы видите, что ваш блок завершения срабатывает несколько раз, по одному для каждого вызова вашей анимации. Обратите внимание, что логическое значение, связанное с блоком завершения, специфично для этого блока завершения, оно никак не относится к другой анимации.

Напомним, что вы испытываете просто эффект параллелизма. Если это не ваше намеренное поведение, вам необходимо соответствующим образом изменить свой код. Если вы хотите, чтобы ваши анимации запускались по одному за раз, вы можете использовать NSLock (NSConditionLock для расширенного управления с использованием переменной условного условия) или, если хотите, мьютекс и библиотеку Posix pthreads напрямую, чтобы создать критический раздел для выполнения по-разному.

+0

Я бы предпочел не использовать NSLock, если это не обязательно. Но я сделаю это, если это единственное решение. Одна вещь, однако, не получается, когда логическое значение будет НЕТ? Поскольку анимация, связанная с этим блоком завершения, фактически не завершена. – gcamp

+0

Я понимаю, что NSLock повредит выступления, однако я не вижу другого решения для сериализации параллельных вызовов. Логическое значение, связанное с обработчиком завершения для блока анимации, никогда не должно быть НЕТ, иначе я не вижу смысла называть его «завершающим» блоком. В любом случае, даже если iOS вызывает блок завершения до того, как связанная анимация фактически прекратится, вы можете просто проверить логическое значение в своем блоке и отреагировать, только если это ДА. –

2

Не уверен, что вы стреляете в анимацию и не зацикливаете ли они (например, с помощью счетчика UIActivityView или что-то в этом роде), - как будто каждый пиксель просматривается в виде таблицы?

В любом случае, возможно, вы могли бы использовать методы делегата UIScrollView и сказать каждую ячейку, чтобы начать анимацию на scrollViewWillBeginDragging: и сказать каждую ячейку, чтобы остановить на scrollViewDidEndDragging:

Вы можете установить логический isAnimating для вашего UITableViewCell и если анимация в настоящее время ведется, ничего не делать.

if (isAnimating) { 
    // ... do nothing 
} else { 
    // Start your animation 
} 

Или придерживаться с тем, что у вас есть сейчас и использовать логическое еще, но только огонь анимации, если это не в настоящее время анимации. Затем в параметре finished просто установите isAnimating на номер NO.

if (isAnimating) { 
     // ... do nothing 
    } else { 
     [UIView animateWithDuration:0.3f 
          animations:^{ 
            // animations... 
            isAnimating = YES; 
            } 
          completion:^{ 
            isAnimating = NO; 
            } 
      ];  
} 
+0

Моя частота кадров в порядке (около 45-50 кадров в секунду). Но ваше решение не будет работать, поскольку «неправильный» блок завершения вызывается, когда «реальная» анимация все еще продолжается. – gcamp

Смежные вопросы