Стратегии обработки изменений состояния приложения
В то время как Ваше приложение находится в том состоянии, для каждого из возможных состояний во время выполнения приложения система имеет различные ожидания. Когда изменения состояния происходят, система уведомляет объект приложения, поочередно уведомляющий его делегата приложения. Можно использовать методы изменения состояния UIApplicationDelegate
протокол, чтобы обнаружить эти изменения состояния и ответить соответственно. Например, при переходе от переднего плана до фона, Вы могли бы выписать любые несохраненные данные и остановить любые продолжающиеся задачи. Следующие разделы предлагают подсказки и руководство для того, как реализовать Ваш код изменения состояния.
Что сделать во время запуска
Когда Ваше приложение будет запущено (или в передний план или в фон), используйте своего делегата приложения application:willFinishLaunchingWithOptions:
и application:didFinishLaunchingWithOptions:
методы, чтобы сделать следующее:
Проверьте содержание словаря опций запуска для получения информации о том, почему приложение было запущено, и ответьте соответственно.
Инициализируйте структуры критических данных своего приложения.
Подготовьте окно своего приложения и представления для дисплея:
Приложения, использующие OpenGL ES для рисования, не должны использовать эти методы для подготовки их среды получения. Вместо этого задержите любой OpenGL вызовы рисования ES к
applicationDidBecomeActive:
метод.Покажите свое окно приложения от Вашего
application:willFinishLaunchingWithOptions:
метод. Задержки UIKit, делающие окно, видимое до окончанияapplication:didFinishLaunchingWithOptions:
возвраты метода.
Во время запуска система автоматически загружает основной файл раскадровки Вашего приложения и загружает начальный контроллер представления. Для приложений, поддерживающих восстановление состояния, машинное оборудование восстановления состояния восстанавливает Ваш интерфейс к своему предыдущему состоянию между вызовами к application:willFinishLaunchingWithOptions:
и application:didFinishLaunchingWithOptions:
методы. Используйте application:willFinishLaunchingWithOptions:
метод, чтобы показать Ваше окно приложения и определить, должно ли восстановление состояния произойти вообще. Используйте application:didFinishLaunchingWithOptions:
метод для внесения любых окончательных корректировок в пользовательский интерфейс приложения.
Ваш application:willFinishLaunchingWithOptions:
и application:didFinishLaunchingWithOptions:
методы должны всегда быть максимально легкими для сокращения времени запуска приложения. Приложения, как ожидают, запустят, инициализируют себя и начнут обрабатывать события меньше чем через 5 секунд. Если приложение не заканчивает свой цикл запуска своевременно, система уничтожает его для того, чтобы быть безразличной. Таким образом любые задачи, которые могли бы замедлить Ваш запуск (такой как доступ к сети) должны быть запланированы выполняемые на вторичном потоке.
Цикл запуска
Когда Ваше приложение запускается, оно перемещается от не состояния выполнения до активного или фонового состояния, переходя кратко через неактивное состояние. Как часть цикла запуска, система создает процесс и основной поток для Вашего приложения и вызывает Ваше приложение main
функция на том основном потоке. Значение по умолчанию main
функция, идущая с Вашим проектом XCode быстро, передает управление к платформе UIKit, выполняющей большую часть работы в инициализации Вашего приложения и подготовке его для выполнения.
Рисунок 4-1 показывает последовательность событий, происходящую, когда приложение запускается в передний план, включая методы делегата приложения, которые вызывают.
Когда Ваше приложение запускается в фон — обычно для обработки некоторого типа фонового события — цикл запуска изменяется немного на один показанный на рисунке 4-2. Основное различие - то, что вместо Вашего приложения, сделанного активным, это вводит фоновое состояние для обработки события и может быть приостановлено в некоторый момент после этого. При запуске в фон система все еще загружает файлы пользовательского интерфейса приложения, но это не выводит на экран окно приложения.
Чтобы определить, начинает ли Ваше приложение передний план или фон, проверьте applicationState
свойство совместно используемого UIApplication
объект в Вашем application:willFinishLaunchingWithOptions:
или application:didFinishLaunchingWithOptions:
метод делегата. Когда приложение запускается в передний план, это свойство содержит значение UIApplicationStateInactive
. Когда приложение запускается в фон, свойство содержит значение UIApplicationStateBackground
вместо этого. Можно использовать это различие для корректировки разового запуском поведения методов делегата соответственно.
Запуск в альбомном режиме
Приложения, который использует только альбомные ориентации для их интерфейса, должны явно попросить, чтобы система запустила приложение в той ориентации. Обычно, приложения запускаются в режиме портрета и поворачивают свой интерфейс для соответствия ориентации устройства по мере необходимости. Для приложения, поддерживающие и портретные и альбомные ориентации, всегда конфигурируйте свои представления для режима портрета и затем позволяйте своим контроллерам представления обработать любые вращения. Если, однако, Ваша среда поддержек приложений, но не портретные ориентации, выполняют следующие задачи заставить его запуститься в альбомном режиме первоначально:
Добавьте
UIInterfaceOrientation
ключ к Вашему приложениюInfo.plist
файл и набор значение этого ключа к такжеUIInterfaceOrientationLandscapeLeft
илиUIInterfaceOrientationLandscapeRight
.Разметьте свои представления в альбомном режиме и удостоверьтесь, что их опции расположения или автокалибровки установлены правильно.
Переопределите свой контроллер представления
shouldAutorotateToInterfaceOrientation:
метод и возвратYES
для левых или правых альбомных ориентаций иNO
для портретных ориентаций.
UIInterfaceOrientation
ключ Info.plist
файл говорит iOS, что он должен сконфигурировать ориентацию панели состояния приложения (если Вы выведены на экран), а также ориентация представлений, которыми управляют любые контроллеры представления во время запуска. Контроллеры представления уважают этот ключ и устанавливают начальную ориентацию их представления для соответствия. Используя этот ключ эквивалентно вызову setStatusBarOrientation:animated:
метод UIApplication
рано в выполнении Вашего applicationDidFinishLaunching:
метод.
Установка специфичных для приложения файлов данных в первом запуске
Можно использовать первый цикл запуска приложения для установки любых данных или конфигурационных файлов, требуемых работать. Специфичные для приложения файлы данных должны быть созданы в Library/Application Support/
<bundleID> / каталог Вашей тестовой среды приложения, где <bundleID> идентификатор пакета Вашего приложения. Можно далее подразделить этот каталог для организации файлов данных по мере необходимости. Можно также создать файлы в других каталогах, такой относительно каталога контейнера iCloud приложения или к локальной переменной Documents
каталог, в зависимости от Ваших потребностей.
Если пакет Вашего приложения содержит файлы данных, которые Вы планируете изменить, копируете те файлы из комплекта приложений и изменить копии. Вы не должны изменять файлы в своем комплекте приложений. Поскольку приложения для iOS являются подписанным кодом, изменение файлов в Вашем комплекте приложений лишает законной силы подпись Вашего приложения и будет препятствовать тому, чтобы Ваше приложение запустилось в будущем. Копирование тех файлов к Application Support
каталог (или другой перезаписываемый каталог в Вашей песочнице) и изменение их существуют единственный способ использовать такие файлы безопасно.
Для получения дополнительной информации о том, куда поместить связанные с приложением файлы данных, см. Руководство по программированию Файловой системы.
Когда Ваше приложение прервано временно, что сделать
Основанные на предупреждении прерывания приводят к временной потере управления Вашим приложением. Ваше приложение продолжает работать на переднем плане, но это не получает сенсорные события от системы. (Это действительно продолжает получать уведомления и другие типы событий, такие как события акселерометра, все же.) В ответ на это изменение Ваше приложение должно выполнить в следующем applicationWillResignActive:
метод:
Сохраните данные и любую соответствующую информацию состояния.
Остановите таймеры и другие периодические задачи.
Остановите любые рабочие запросы метаданных.
Не инициируйте новые задачи.
Воспроизведение фильма паузы (кроме тех случаев, когда, воспроизводя по AirPlay).
Введите в состояние паузы, если Ваше приложение является игрой.
Возвратите OpenGL к исходному состоянию частоты кадров ES.
Временно отстраните любые очереди отгрузки или очереди работы, выполняющие некритический код. (Можно продолжать обрабатывать сетевые запросы и другие чувствительные ко времени фоновые задачи, в то время как неактивный.)
Когда Ваше приложение попятилось к активному состоянию, applicationDidBecomeActive:
метод должен инвертировать любой из шагов, принятых applicationWillResignActive:
метод. Таким образом, на оживление, Ваше приложение должно перезапустить таймеры, очереди отгрузки резюме, и отрегулировать OpenGL частоты кадров ES снова. Однако игры не должны возобновляться автоматически; они должны остаться приостановленными, пока пользователь не принимает решение возобновить их.
Когда пользователь нажимает кнопку Sleep/Wake, приложения с файлами, защищенными NSFileProtectionComplete
опция защиты должна закрыть любые ссылки на те файлы. Для устройств, сконфигурированных с надлежащим паролем, нажимая кнопку Sleep/Wake, блокирует экран и вынуждает систему выбросить ключи расшифровки для файлов с включенной полной защитой. В то время как экран заблокирован, любые попытки получить доступ к соответствующим файлам перестанут работать. Таким образом, если у Вас есть такие файлы, необходимо закрыть любые ссылки на них в Вашем applicationWillResignActive:
метод и открытые новые ссылки в Вашем applicationDidBecomeActive:
метод.
Ответ на временные прерывания
Когда основанное на предупреждении прерывание происходит, такие как входящий телефонный вызов, приложение перемещается временно в неактивное состояние так, чтобы система могла предложить пользователю о том, как продолжить. Приложение остается в этом состоянии, пока пользователь не отклоняет предупреждение. В этой точке приложение или возвращается к активному состоянию или перемещается в фоновое состояние. Когда основанное на предупреждении прерывание происходит, рисунок 4-3 показывает поток событий через Ваше приложение.
Уведомления, выводящие на экран баннер, не деактивировали Ваше приложение в способе, которым делают основанные на предупреждении уведомления. Вместо этого баннер положен вдоль главного края Вашего окна приложения, и Ваше приложение продолжается, получают сенсорные события как прежде. Однако, если пользователь раскрывает баннер для раскрытия центра уведомления, приложение перемещается в неактивное состояние так же, как если бы произошло основанное на предупреждении прерывание. Ваше приложение остается в неактивном состоянии, пока пользователь не распускает центр уведомления или запускает другое приложение. В этой точке Ваше приложение перемещается в надлежащее активное или фоновое состояние. Пользователь может использовать приложение Настроек для конфигурирования, какие уведомления выводят на экран баннер и которые выводят на экран предупреждение.
Нажатие кнопки Sleep/Wake является другим типом прерывания, заставляющего Ваше приложение быть деактивированным временно. То, когда пользователь нажимает эту кнопку, система отключает сенсорные события, перемещает приложение в фон, устанавливает значение приложения applicationState
свойство к UIApplicationStateBackground
, и блокирует экран. Заблокированный экран имеет дополнительные последствия для приложений что защита данных использования для шифрования файлов. Те последствия описаны в том, Что Сделать, Когда Ваше Приложение Прервано Временно.
Когда Ваше приложение вводит передний план, что сделать
Возврат переднему плану является шансом Вашего приложения перезапустить задачи, которые это остановило, когда это переместилось в фон. Шаги, происходящие при перемещении в передний план, показаны на рисунке 4-4. applicationWillEnterForeground:
метод должен отменить что-либо, в чем выполнили Ваш applicationDidEnterBackground:
метод, и applicationDidBecomeActive:
метод должен продолжать выполнять те же задачи активации, что он был бы во время запуска.
Будьте подготовлены обработать уведомления с очередями
Приложение в состоянии ожидания должно быть готово обработать любые уведомления с очередями, когда это возвращается к приоритетному или фоновому режиму выполнения. Приостановленное приложение не выполняет кода и поэтому не может обработать уведомления, связанные с изменениями ориентации, изменениями времени, предпочтительными изменениями и многими другими, которые влияли бы на появление или состояние приложения. Для проверки эти изменения не потеряны, системные очереди много соответствующих уведомлений, и поставляет им приложению, как только оно начинает выполнять код снова (или на переднем плане или на фоне). Препятствовать тому, чтобы Ваше приложение стало, перегрузилось с уведомлениями, когда оно возобновляется, система объединяет события и поставляет единственное уведомление (каждого соответствующего типа), который отражает чистое изменение, так как было приостановлено Ваше приложение.
Таблица 4-1 перечисляет уведомления, которые могут быть объединены и поставлены Вашему приложению. Большинство этих уведомлений поставлено непосредственно зарегистрированным наблюдателям. Некоторые, как связанные с изменениями ориентации устройства, обычно прерываются системной платформой и поставляются Вашему приложению в другом отношении.
Событие | Уведомления |
---|---|
Аксессуар соединяется или разъединяется. | |
Изменения ориентации устройства. |
В дополнение к этому уведомлению контроллеры представления обновляют свои интерфейсные ориентации автоматически. |
Существует значительное изменение времени. | |
Уровень заряда батареи или изменения состояния батареи. | |
Изменения состояния близости. | |
Состояние защищенных изменений файлов. | |
Внешний дисплей соединяется или разъединяется. | |
Экранный режим дисплея изменяется. | |
Предпочтения, которые Ваше приложение представляет через измененное приложение Настроек. | |
Текущий язык или настройки локали изменились. | |
Состояние учетной записи iCloud пользователя изменилось. |
Уведомления с очередями поставлены на основном цикле выполнения Вашего приложения и обычно поставляются перед любыми сенсорными событиями или другим вводом данных пользователем. Большинство приложений должно быть в состоянии обработать эти события достаточно быстро, что они не вызвали бы значимой задержки, когда возобновлено. Однако, если Ваше приложение кажется вялым, когда оно возвращается из фонового состояния, используйте Инструменты, чтобы определить, вызывает ли Ваш код обработчика уведомления задержку.
Приложение, возвращающееся в передний план также, получает уведомления обновления представления для любых представлений, отмеченных грязные начиная с последнего обновления. Приложение, работающее в фоновом режиме, может все еще вызвать setNeedsDisplay
или setNeedsDisplayInRect:
методы для запроса обновления на его представления. Однако, потому что представления не видимы, система объединяет запросы и обновляет представления только после того, как приложение возвращается в передний план.
Обработайте Изменения iCloud
Если состояние изменений iCloud по какой-либо причине, система поставляет a NSUbiquityIdentityDidChangeNotification
уведомление Вашему приложению. Состояние iCloud изменяется, когда пользователь входит в систему, или из iCloud считают, или включает или отключает синхронизацию документов и данных. Это уведомление является сигналом Вашего приложения для обновления кэшей и любых связанных с iCloud элементов пользовательского интерфейса для размещения изменения. Например, когда пользователь выходит из iCloud, необходимо удалить ссылки на все основанные на iCloud файлы или данные.
Если Ваше приложение уже предложило пользователю о том, хранить ли файлы в iCloud, не запрашивайте снова, когда изменяется состояние iCloud. После запроса пользователя в первый раз, сохраните выбор пользователя в локальных предпочтениях своего приложения. Вы могли бы тогда хотеть представить то предпочтение с помощью пакета Настроек или как опции в приложении. Но не повторяйте подсказку снова, если то предпочтение в настоящее время не находится в пользовательской базе данных значений по умолчанию.
Изменения локали дескриптора
Если пользователь изменяет текущую локаль, в то время как Ваше приложение приостановлено, можно использовать NSCurrentLocaleDidChangeNotification
уведомление для принуждения обновлений к любым представлениям, содержащим уязвимую информацию локали, таким как даты, времена и числа, когда приложение возвращается в передний план. Конечно, лучший способ избежать связанных с локалью проблем состоит в том, чтобы записать Ваш код способами, упрощающими обновлять представления. Например:
Используйте
autoupdatingCurrentLocale
метод класса при полученииNSLocale
объекты. Этот метод возвращает объект языкового стандарта, обновляющий себя автоматически в ответ на изменения, таким образом, Вы никогда не должны воссоздавать его. Однако, когда локаль изменяется, все еще необходимо обновить представления, содержащие содержание, полученное из текущей локали.Воссоздайте любую кэшируемую дату и объекты средства форматирования числа каждый раз, когда изменяется текущая информация о локали.
Для получения дополнительной информации об интернационализации Вашего кода для обработки изменений локали посмотрите Руководство по Интернационализации и Локализации.
Изменения дескриптора в настройках Вашего приложения
Если Ваше приложение имеет настройки, которыми управляет приложение Настроек, оно должно наблюдать NSUserDefaultsDidChangeNotification
уведомление. Поскольку пользователь может изменить настройки, в то время как Ваше приложение приостановлено или в фоновом режиме, можно использовать это уведомление для реакции на любые важные изменения в тех настройках. В некоторых случаях ответ на это уведомление может помочь близко потенциальной дыре в системе безопасности. Например, почтовая программа должна реагировать на изменения в сведениях об аккаунте пользователя. Отказ наблюдать эти изменения мог вызвать конфиденциальность или проблемы безопасности. В частности, даже если учетная запись больше не принадлежит тому лицу, текущий пользователь мог бы быть в состоянии послать электронное письмо с помощью старых сведений об аккаунте.
После получения NSUserDefaultsDidChangeNotification
уведомление, Ваше приложение должно перезагрузить любые соответствующие настройки и, при необходимости, сбросить его пользовательский интерфейс соответственно. В случаях, где пароли или другая связанная с безопасностью информация изменился, необходимо также скрыть любую ранее выведенную на экран информацию и вынудить пользователя ввести новый пароль.
Когда Ваше приложение вводит фон, что сделать
При перемещении от переднего плана до фонового выполнения используйте applicationDidEnterBackground:
метод Вашего приложения делегирует, чтобы сделать следующее:
Подготовьте брать изображение своего приложения. Когда Ваш
applicationDidEnterBackground:
возвраты метода, система делает снимок пользовательского интерфейса Вашего приложения и использует получающееся изображение для анимаций перехода. Если какие-либо представления в Вашем интерфейсе содержат уязвимую информацию, необходимо скрыть или изменить те представления передapplicationDidEnterBackground:
возвраты метода. Если Вы добавляете новые представления к своей иерархии представления как часть этого процесса, необходимо вынудить те представления привлечь себя, как описано в Подготавливаются к Снимку Приложения.Сохраните любую информацию состояния соответствующего приложения. До ввода фона Ваше приложение должно было уже сохранить все критические пользовательские данные. Используйте переход к фону для сохранения любых последних изменений в состоянии приложения.
Высвободите память по мере необходимости. Выпустите любые кэшированные данные, что Вы не нуждаетесь и делаете любую простую очистку, которая могла бы сократить объем потребляемой памяти Вашего приложения. Приложения с местами памяти большой емкости являются первыми, чтобы быть завершенными системой, поэтому высвободите средства изображения, кэши данных и любые другие объекты, в которых Вы больше не нуждаетесь. Для получения дополнительной информации посмотрите, Сокращают Ваш Объем потребляемой памяти.
Ваш делегат приложения applicationDidEnterBackground:
метод имеет приблизительно 5 секунд для окончания любых задач и возврата. На практике этот метод должен возвратиться как можно быстрее. Если метод не возвращается, прежде чем время заканчивается, Ваше приложение уничтожено и очищено из памяти. При тихой необходимости в большем количестве времени для выполнения задач, вызовите beginBackgroundTaskWithExpirationHandler:
метод, чтобы запросить фоновое время выполнения и затем запустить любые продолжительные задачи во вторичном потоке. Независимо от того, начинаете ли Вы какие-либо фоновые задачи, applicationDidEnterBackground:
метод должен все еще выйти в течение 5 секунд.
В зависимости от функций Вашего приложения существуют другие вещи, которые Ваше приложение должно сделать при перемещении в фон. Например, любые активные службы Bonjour должны быть приостановлены, и приложение должно прекратить вызывать OpenGL функции ES. Для списка вещей Ваше приложение должно сделать при перемещении в фон, видеть Быть Ответственным Фоновым приложением.
Фоновый цикл перехода
То, когда пользователь нажимает кнопку «Домой», нажимает кнопку Sleep/Wake, или система запускает другое приложение, приоритетные переходы приложения к неактивному состоянию и затем к фоновому состоянию. Эти переходы приводят к вызовам делегату приложения applicationWillResignActive:
и applicationDidEnterBackground:
методы, как показано на рисунке 4-5. После возврата из applicationDidEnterBackground:
метод, большинство приложений перемещается в состояние ожидания вскоре позже. Приложения, запрашивающие определенные фоновые задачи (такие как игра музыки) или тот запрос немного дополнительного времени выполнения от системы, могут продолжать работать некоторое время дольше.
Подготовитесь к снимку приложения
Вскоре после делегата приложения applicationDidEnterBackground:
возвраты метода, система берет снимок окон приложения. Точно так же, когда приложение разбужено для выполнения фоновых задач, система может взять новый снимок для отражения любых соответствующих изменений. Например, когда приложение разбужено для обработки загруженных элементов, система берет новый снимок так, чтобы мог отразить любые изменения, вызванные объединением элементов. Система использует эти изображения снимка в многозадачном UI для показа состояния приложения.
При внесении изменений в представления о вводе фона можно вызвать snapshotViewAfterScreenUpdates:
метод Вашего основного представления, чтобы вынудить те изменения, которые будут представлены. Вызов setNeedsDisplay метода на представлении неэффективен для снимков, потому что снимок взят перед следующим циклом получения, таким образом препятствуя тому, чтобы были представлены любые изменения. Вызов snapshotViewAfterScreenUpdates:
метод со значением YES
вызывает незамедлительное обновление до базовых буферов, которые использует машинное оборудование снимка.
Сократите свой объем потребляемой памяти
Каждое приложение должно высвободить столько памяти, сколько практично после ввода фона. Система пытается сохранить как много приложений в памяти в то же время, что и это может, но когда память кончается, это завершает приостановленные приложения для предъявления претензий в отношении той памяти. Приложения, использующие большие объемы памяти, в то время как в фоновом режиме первые приложения, которые будут завершены.
В сущности Ваше приложение должно удалить сильные ссылки к объектам, как только они больше не необходимы. Удаление сильных ссылок предоставляет компилятору возможность выпустить объекты сразу же так, чтобы в отношении соответствующей памяти можно было предъявить претензии. Однако, если Вы хотите кэшировать некоторые объекты улучшить производительность, можно ожидать до переходов приложения к фону прежде, чем удалить ссылки на них.
Некоторые примеры объектов, которые необходимо удалить сильные ссылки, чтобы как можно скорее включать:
Объекты изображения Вы создали. (Некоторые методы
UIImage
возвратите изображения, данные основного изображения которых очищены автоматически системой. Для получения дополнительной информации посмотрите обсуждение в обзоре Ссылки класса UIImage.)Большие носители или файлы данных, которые можно загрузить снова из диска
Любые другие объекты, в которых Ваше приложение не нужно и может воссоздать легко позже
Когда Ваше приложение перемещается в фон, чтобы помочь сократить объем потребляемой памяти Вашего приложения, система автоматически производит чистку некоторых данных, выделенных от имени Вашего приложения.
Система производит чистку запоминающего устройства для всех Базовых Слоев анимации. Это усилие не удаляет расположенные на слое объекты Вашего приложения из памяти, и при этом оно не изменяет свойства текущего слоя. Это просто препятствует тому, чтобы содержание тех уровней появилось на экране, который, учитывая, что приложение в фоновом режиме, не должен происходить так или иначе.
Это удаляет любые системные ссылки на кэшируемые изображения.
Это удаляет сильные ссылки к некоторым другим кэшам системных управляемых данных.