Точный момент, когда iOS делает снимок вида при вводе фона?
У меня проблема с переводом приложения iPhone в фоновый режим, нажав кнопку выхода, а затем снова запустив его, нажав на значок запуска на главном экране: представление приложения возвращается в исходное состояние, как я хочу, но до этого оно мигает. ранее, ненадлежащее состояние на экране кратко.
Фон
Мой основной вид состоит в основном из последовательности связанных вызовов UIAnimateWithDuration. Поведение, которое я хочу всякий раз, когда происходит какое-либо прерывание, состоит в том, чтобы вернуть анимацию в ее начальное состояние (если анимация не завершилась и приложение не перешло в статическую финальную фазу), и начинать заново с этого момента, когда приложение возвращается в активное и видимое состояние ,
После изучения предмета, который я выучил, мне нужны два типа кода обработки прерываний, чтобы обеспечить хороший UX: «мгновенный» и «плавный». У меня есть метод resetAnimation, который мгновенно сбрасывает свойства представления в начальное состояние, и метод pauseAnimation, который быстро анимирует в то же состояние, с дополнительной меткой, указывающей, что «пауза» исчезает в верхней части представления.
Двойной щелчок по кнопке выхода
Причиной этого является вариант использования «кнопки двойного нажатия», который на самом деле не скрывает ваш вид и не переводит вас в фоновое состояние, он просто немного прокручивается вверх, чтобы отобразить меню многозадачности внизу. Итак, мгновенный сброс состояния просмотра в этом случае выглядел очень уродливо. Анимированный переход и информирование пользователя о том, что вы остановились, казались лучшей идеей.
Этот случай работает хорошо и плавно, реализуя метод делегата applicationWillResignActive в моем делегате приложения и вызывая оттуда pauseAnimation. Я обрабатываю возврат из этого меню многозадачности, реализуя метод делегата applicationDidBecomeActive и вызывая оттуда мой метод resumeAnimation, который затухает в метке «приостановлено», если она есть, и запускает мою последовательность анимации из исходного состояния.
Все это прекрасно работает, нигде не мерцает.
Посещение с обратной стороны
Мое приложение построено на основе шаблона "утилиты" Xcode, поэтому оно имеет перевернутый вид для отображения информации / настроек. Я обрабатываю посещение обратной стороны и возвращаюсь к основному виду, реализуя эти два метода делегата в моем контроллере основного вида:
(Пустоты) viewDidDisappear: (BOOL) анимированные
(Пустоты) viewDidAppear: (BOOL) анимированные
Я вызываю метод resetAnimation в методе viewDidDisappear и возобновляю анимацию в viewDidAppear. Все это работает отлично, основной вид - это его начальное состояние с самого начала перехода в видимое состояние - никаких неожиданных миганий неправильных состояний анимации чего-либо. Но:
Нажав кнопку выхода и перезапустив с моего значка приложения (глючная часть!)
Вот тут и начинается беда. Когда я нажимаю кнопку выхода один раз, и мое приложение начинает переходить в фоновый режим, происходят две вещи. Во-первых, здесь вызывается applicationWillResignActive, поэтому запускается и мой метод pauseAnimation. В этом нет необходимости, поскольку переход не обязательно должен быть плавным - вид просто статичен и «масштабируется», чтобы показать домашний экран - но что вы можете сделать? Что ж, это не принесет никакого вреда, если бы я мог просто вызвать resetAnimation до того момента, когда система сделает снимок представления.
В любом случае, во-вторых, вызывается applicationDidEnterBackground в делегате приложения. Я попытался вызвать resetAnimation оттуда, чтобы представление было в правильном состоянии, когда приложение вернется, но это, похоже, не работает. Кажется, что «снимок» уже сделан, и поэтому, когда я нажимаю значок запуска моего приложения и перехожу, неправильное состояние просмотра кратковременно мигает на экране, прежде чем отображается правильное начальное состояние. После этого все работает нормально, анимации идут так, как они должны, но этот мерзкий миг в тот момент перезапуска не исчезнет, что бы я ни пытался.
По сути, что мне нужно, в какой именно момент система делает этот снимок? И, следовательно, какой будет правильный метод делегата или обработчик уведомлений, чтобы подготовить мой взгляд к съемке «сувенирной фотографии»?
PS. Кроме того, существует файл default.png, который, по-видимому, отображается не только при первом запуске, но и всякий раз, когда процессор испытывает затруднения или возвращается в приложение, по какой-то другой причине на некоторое время задерживается. Это немного некрасиво, особенно если вы возвращаетесь к своему перевернутому виду, который выглядит совершенно иначе, чем ваш вид по умолчанию. Но это такая основная функция iOS, я думаю, мне даже не стоит пытаться выяснить или контролировать это :)
Изменить: так как люди спрашивали фактический код, и мое приложение уже было выпущено после того, как задал этот вопрос, я выложу некоторые здесь. (Приложение называется Sweetest Kid, и если вы хотите увидеть, как оно на самом деле работает, оно здесь:http://itunes.apple.com/app/sweetest-kid/id476637106?mt=8 )
Вот мой метод pauseAnimation - resetAnimation практически идентичен, за исключением того, что его вызов анимации имеет нулевую продолжительность и задержку, и он не показывает метку «Приостановлено». Одна из причин, по которой я использую UIAnimation для сброса значений вместо простого присвоения новых значений, заключается в том, что по какой-то причине анимации просто не прекратились, если я не использовал UIAnimation. В любом случае, вот метод pauseAnimation:
- (void)pauseAnimation {
if (currentAnimationPhase < 6 || currentAnimationPhase == 255) {
// 6 means finished, 255 is a short initial animation only showing at first launch
self.paused = YES;
[UIView animateWithDuration:0.3
delay:0
options:UIViewAnimationOptionAllowUserInteraction |
UIViewAnimationOptionBeginFromCurrentState |
UIViewAnimationOptionCurveEaseInOut |
UIViewAnimationOptionOverrideInheritedCurve |
UIViewAnimationOptionOverrideInheritedDuration
animations:^{
pausedView.alpha = 1.0;
cameraImageView.alpha = 0;
mirrorGlowView.alpha = 0;
infoButton.alpha = 1.0;
chantView.alpha = 0;
verseOneLabel.alpha = 1.0;
verseTwoLabel.alpha = 0;
verseThreeLabel.alpha = 0;
shine1View.alpha = stars1View.alpha = stars2View.alpha = 0;
shine1View.transform = CGAffineTransformIdentity;
stars1View.transform = CGAffineTransformIdentity;
stars2View.transform = CGAffineTransformIdentity;
finishedMenuView.alpha = 0;
preparingMagicView.alpha = 0;}
completion:^(BOOL finished){
pausedView.alpha = 1.0;
cameraImageView.alpha = 0;
mirrorGlowView.alpha = 0;
infoButton.alpha = 1.0;
chantView.alpha = 0;
verseOneLabel.alpha = 1.0;
verseTwoLabel.alpha = 0;
verseThreeLabel.alpha = 0;
shine1View.alpha = stars1View.alpha = stars2View.alpha = 0;
shine1View.transform = CGAffineTransformIdentity;
stars1View.transform = CGAffineTransformIdentity;
stars2View.transform = CGAffineTransformIdentity;
finishedMenuView.alpha = 0;
preparingMagicView.alpha = 0;
}];
askTheMirrorButton.enabled = YES;
againButton.enabled = NO;
shareOnFacebookButton.enabled = NO;
emailButton.enabled = NO;
saveButton.enabled = NO;
currentAnimationPhase = 0;
[[cameraImageView subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)]; // To remove the video preview layer
}
}