Низкая частота кадров во время push-перехода UINavigationController - PullRequest
2 голосов
/ 29 ноября 2010

У меня есть UINavigationController, и нажмите от корневого контроллера представления к следующему контроллеру представления.Этот контроллер второго вида довольно «тяжелый», так как он имеет много инициализации и подпредставлений.

Моя проблема заключается в следующем: анимация перехода работает ужасно.В основном, анимация страдает от очень низкой частоты кадров (я получаю, может быть, 3-4 кадра в общей сложности из "push" анимации).

Я испробовал множество различных техник, включая два разных методавручную анимировать переход.Во всех случаях первые 0,4-0,7 секунды анимации страдают от этой плохой частоты кадров.Если я установлю переход на 5 секунд, например, первая половина секунды или около того будет работать плохо, но остальная часть анимации будет красивой и плавной.

Это заставляет меня поверить, что «что-то» происходитв начале перехода - то, что заставляет устройство анимироваться с очень низкой частотой кадров.

После введения большого количества операторов NSLog в мой код я увидел две вещи.Во-первых, очевидно, что вторая точка зрения загружается во время push.Я исправил это, получив доступ к геттеру в свойстве view перед выполнением push.Я могу подтвердить, что это приводит к тому, что вся инициализация происходит до начала анимации нажатия.

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

Мой вопрос: Кто-нибудь еще испытывал низкую частоту кадров при анимации push-перехода UINavigationController, но только в течение первых 0,4-0,7 секунд анимации?За кулисами происходит что-то еще, что вызывает это, и можно ли что-нибудь сделать?

Для справки, вот мой текущий код, который загружается и перемещается к следующему представлению.Я намеренно обращаюсь к получателю представления, чтобы заставить представление загрузить и инициализировать перед переходом (главным образом, чтобы исключить это как проблему).Этот код выполняется в основном потоке с использованием performSelectorOnMainThread::: в ответ на обратный вызов веб-службы.

PlayingFieldViewController *v = [[PlayingFieldViewController alloc] initWithNibName:@"PlayingFieldView" bundle:[NSBundle mainBundle]];
UIView *lazy = v.view;
[appDelegate.navigationController pushViewController:v animated:YES];
[v release];

Я также попробовал несколько других методов анимации, все с тем же результатом:

CATransition *transition = [CATransition animation];
transition.duration = 1.0;
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromRight;
[appDelegate.navigationController.view.layer addAnimation:transition forKey:kCATransition];
[appDelegate.navigationController pushViewController:v animated:NO];

и:

[UIView 
  transitionWithView:appDelegate.navigationController.view
  duration:1.0
  options:UIViewAnimationOptionTransitionCurlUp
  animations:^{
   [appDelegate.navigationController pushViewController:v animated:NO];
  }
  completion:NULL];

Ответы [ 2 ]

4 голосов
/ 30 ноября 2010

После дальнейшего тестирования мне удалось диагностировать проблему.Второй вид включает в себя много UIImageViews.Удаление этих представлений или их скрытие решает проблему.

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

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

0 голосов
/ 29 ноября 2010

Я не наткнулся на это с помощью контроллера навигации, но я получил почти такой же результат, когда обновлял представление таблицы из другого потока, пользовательский интерфейс сначала медленно обновлялся, но после небольшой задержки все снова показывалось. Как отмечает Джастин в комментарии, вы должны работать с пользовательским интерфейсом в основном потоке. Простой способ сделать это - обернуть ваш вызов в пользовательский интерфейс в блок GCD:

dispatch_sync(dispatch_get_main_queue(), ^{
// Do UI stuff here
});

или используйте

performSelectorOnMainThread:withObject:waitUntilDone:

...