Сохранение состояния iOS-приложения

В iOS 6 помимо всего прочего появилась полезная для разработчиков возможность – автоматизированный процесс сохранения и восстановления состояния приложения.

До выхода iOS 4, в которой была реализована многозадачность, приложения должны были сами заботиться о том, чтобы сохранить и восстановить свой внешний вид при перезапуске. Каждый разработчик решал эту задачу по-своему. С выходом iOS 4 этот вопрос отошел на второй план – приложение можно “убрать” в фон и “вернуть” обратно без дополнительных затрат.

Однако, приложения, находящиеся в фоне, могут быть закрыты системой, чтобы дать активному приложению больше памяти – ее объем на устройстве ограничен. Таким образом, пользователь может, сам того не желая, закрыть приложение, с которым он только что работал, просто переключившись на другое приложение.

Чтобы упростить жизнь авторам приложений, в iOS 6 SDK были добавлены средства, позволяющие упростить процесс сохранения и восстановления состояния приложения. Причем, значительная часть из них работает без написания кода. Рассмотрим базовые возможности, доступные разработчикам.

Сохранение и восстановление не является обязательным для приложений
Разработчики должны “выразить желание” воспользоваться средствами сохранения и восстановления состояния приложения. Для этого необходимо реализовать два метода в делегате приложения.

- (BOOL)application:(UIApplication *)application shouldSaveApplicationState:(NSCoder *)coder
{
    return YES;
}

- (BOOL)application:(UIApplication *)application shouldRestoreApplicationState:(NSCoder *)coder
{
    return YES;
}

Если эти методы не реализованы или возвращают NO, приложение не будет использовать средства сохранения и восстановления состояния.

Можно внедрять сохранение и восстановление по частям
Не требуется сразу добавлять поддержку во все контроллеры, переделывать приложение полностью. Можно реализовывать это поэтапно, контроллер за контроллером.

Сохранение UIViewController и UIView
Основную работу по сохранению объектов UIKit делает сам. Для этого необходимо для всех сохраняемых объектов указывать Restoration ID в Interface Builder.

Restoration ID

Для контроллеров лучше всего использовать Restoration ID, идентичный Storyboard ID, для представлений – выбрать уникальный Restoration ID в пределах контроллера.
При указанном Restoration ID система будет сохранять все необходимые свойства контроллеров и представлений, позволяя затем восстановить их в том же виде.

Однако, разработчикам также необходимо предпринять определенные меры. Система сохраняет свойства базовых классов (свойства UIViewController, UITableViewController, свойства сохраняемых UITableView, UILabel и т.д.). Свойства, определенные в классах-наследниках разработчик должен сохранять сам.

Делается это способом, схожим с сохранением состояния объектов. Необходимо реализовать два метода.

- (void)encodeRestorableStateWithCoder:(NSCoder *)coder
{
    [super encodeRestorableStateWithCoder:coder];

    // save state properties into coder...
    // [coder encodeObject:self.delegate forKey:@"delegate"];
}

- (void)decodeRestorableStateWithCoder:(NSCoder *)coder
{
    [super decodeRestorableStateWithCoder:coder];

    // restore state properties from coder...
    // self.delegate = [coder decodeObjectForKey:@"delegate"];
}

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

Небольшое замечение. Эти методы в контроллерах вызываются ПОСЛЕ -viewDidLoad: и ДО -viewWillAppear:, необходимо учитывать это при восстановлении свойств контроллера.

Что нужно сохранять?
В теории можно сохранять вообще все свойства объектов, однако, это не является оптимальным решением. Общей рекомендацией будет – сохранять все передаваемые контроллеру параметры (его публичные readwrite-свойства), все изменяемые в течение жизни контроллера параметры. Объекты, которые и так хранятся в приложении сохранять не нужно (например, объекты Core Data, достаточно только сохранять их идентификаторы).
При указании Restoration ID для контроллера, необходимо также указать его и для всех представлений, состояние которых может меняться и должно быть сохранено (например, UITableView или UITextField), не стоит сохранять состояние статических элементов (например, UILabel). Также не обязательно сохранять состояние элементов, которые инициализуются один раз во -viewWillAppear: или -viewDidLoad:.

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

Стоит почитать документацию Apple, посмотреть видео с WWDC2012, посвященное сохранению и восстановлению.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s