2010-11-05 6 views
17

У меня есть элемент интерфейса вращающегося круга, который обновляется NSTimer. У меня также есть UIScrollView, который будет «блокировать» вращающийся круг во время прокрутки. Это ожидалось, потому что таймер и вид прокрутки выглядят как в одном потоке.Мои пользовательские элементы пользовательского интерфейса не обновляются, пока прокручивается UIScrollView.

Так что я поставил таймер в отдельную тему, которая в основном отлично работает! Я вижу, что он работает, потому что NSLogs продолжают появляться даже при прокрутке.

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

Любые идеи, что я могу сделать? Благодаря!

ответ

42

При прокрутке цикл запуска основной резьбы находится в UITrackingRunLoopMode. Поэтому вам нужно запланировать таймер в этом режиме (возможно, в дополнение к режиму по умолчанию). Я считаю, что NSRunLoopCommonModes включает в себя как режим отслеживания событий по умолчанию и, таким образом, вы можете просто сделать это:

NSTimer *timer = [NSTimer timerWithTimeInterval:0.42 target:foo selector:@selector(doSomething) userInfo:nil repeats:YES]; 
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; 

Кстати, вы должны сделать все это в основном потоке. Не нужно создавать фоновый поток (если только каждый вызов таймера не выполняет некоторую длительную обработку).

+0

+1, отлично работает для меня. – pt2ph8

+0

Вы правы, NSRunLoopCommonModes - правильный режим для этого, спасибо! Я избавился от фоновой нити, и теперь срабатывает таймер, даже во время прокрутки.Но моя проблема все еще существует, перерисовки не происходит. – Sebastian

+0

Что вы делаете, чтобы вызвать перерисовку? Я думаю, что 'setNeedsDisplay' будет делать трюк. Возможно, вам следует отправить свой метод таймера. –

0

Вы правы, что UIScrollView не обновляет свой контент во время прокрутки.

Возможно, ваша лучшая ставка - и это что-то вроде взлома - это отображение вашего анимационного представления отдельно (возможно, в рамке, чтобы получить бесплатное обрезание) и использовать обратные вызовы делегата прокрутки для поиска выведите текущую позицию прокрутки и соответствующим образом расположите свою анимацию.

ПРИМЕЧАНИЕ: это предложение a hack! Это не лучшие практики, и это, безусловно, противоречит простому, поддерживаемому коду без побочных эффектов. Тем не менее, это единственный способ, которым я могу думать, чтобы получить нужный дисплей.

Еще одна ссылка: переосмыслить важность отображения анимированного содержимого прокрутки во время прокрутки.

+0

Нет, анимационный вращающийся круг НЕ является частью содержимого прокрутки! Извините, может быть, я не был уверен в этом. – Sebastian

3

UIScrollView не только блокирует NSTimers, но и блокирует весь основной поток. И объекты UIKit должны быть доступны только в основном потоке (и, часто, ограничены непредсказуемыми способами, если вы пытаетесь уклониться от этого ограничения), что, вероятно, поэтому - даже если у вас есть часы, поступающие из внешнего потока - вы «Не удается опубликовать обновления.

Это немного уловка, но есть ли способ, которым ваша анимация может быть достигнута с помощью CoreAnimation? Вещи, связанные с этим, продолжают работать независимо от того, что происходит в основной теме.

+0

Ну, таймер не заблокирован вообще. Теперь я запускаю основной поток в NSRunLoopCommonModes, и он срабатывает даже во время прокрутки. Но мой взгляд не перерисовывается, по крайней мере, не через механизм setNeedsDisplay/display UIView. Документы говорят: «Любые объекты UIView, помеченные как необходимость отображения, автоматически отображаются повторно, когда приложение возвращается в цикл выполнения». – Sebastian

+0

CA - отличная идея, я попробую! – Sebastian

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