Как заставить представление визуализировать себя?

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

Увеличенное представление специально разработано, что создает большую проблему при таком подходе. Если я создаю увеличенный вид в моем главном виде viewDidLoad метод и установить его кадр в полноэкранный размер, вид drawRect метод вызывается немедленно, и представление корректно отображается в натуральную величину. Если я затем использую этот вид в анимации, все работает как положено.

Тем не менее, мне нужно, чтобы это увеличенное представление было разным в зависимости от того, какое подпредставление было задействовано, поэтому мне нужно каждый раз заново его создавать / перерисовывать. Проблема в том, что когда я делаю это в ответ на сенсорное событие, представление drawRect Метод не вызывается до тех пор, пока не начнется анимация, и в это время кадр представления будет маленьким, а не полноэкранным, и в результате все будет отображаться неправильно.

В моем коде для события касания я явно устанавливаю рамку представления в полноэкранный режим и вызываю setNeedsDisplay до запуска анимации, но это не имеет никакого эффекта - drawRect просто не вызывается, пока не начинается анимация.

Есть ли способ заставить перерисовку, чтобы представление отображалось в то время, как его размер соответствует желаемому?

4 ответа

Решение

Как я прокомментировал выше, Джо задал здесь нечто подобное (в качестве более общего вопроса), на который Том Свифт дал ответ, который манипулирует текущим циклом выполнения.

Он предложил форсировать цикл выполнения через одну итерацию сразу после вызова -setNeedsDisplay используя следующий код:

[[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate: [NSDate date]];

Есть некоторые предостережения в отношении этого подхода, которые обсуждаются в комментариях.

Также там было указано, что

[CATransaction flush];

может также достичь того же эффекта принудительного перерисовки представления.

Правильный способ сделать это - просто разделить ваш метод.

Просто позвони setNeedsDisplayзатем вернитесь без анимации. Подождите, пока drawRect который все настраивает правильно, завершил перерисовку, а затем поставил в очередь другой метод, который запускает желаемую анимацию (посредством постановки в очередь операции или уведомления). Затем запустите анимацию. Все это может происходить довольно быстро (с частотой кадров) и не требует дополнительных (опасных) рекурсивных вызовов цикла выполнения или CATransaction вызовы (которые могут вызвать дополнительные настройки GPU).

После звонка setNeedsDisplay для вызова drawRect может потребоваться некоторое время. Начните анимацию с небольшой (0.1f) задержкой. Вы также можете вызвать метод анимации из [self executeSelector:withObject:afterDelay:], чтобы добавить задержку, если это проще.

Инженер Apple предоставил альтернативное рекомендуемое решение. Используйте 2 UIViews, один маленький и один большой, с большим с альфа-0. Рендеринг обоих, установите кадр большого, маленький, с анимацией перекрестного затухания, а также увеличьте оба размера от маленького до большого.

Другие вопросы по тегам