Как заставить представление визуализировать себя?
В моем приложении у меня есть несколько небольших подпредставлений. Когда пользователь нажимает на подпредставление, я помещаю одно отдельное представление поверх прослушиваемого подпредставления (того же размера), а затем анимирую это отдельное представление в полноэкранный размер.
Увеличенное представление специально разработано, что создает большую проблему при таком подходе. Если я создаю увеличенный вид в моем главном виде 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. Рендеринг обоих, установите кадр большого, маленький, с анимацией перекрестного затухания, а также увеличьте оба размера от маленького до большого.