Сохранение пользовательских настроек с помощью NSUserDefaults

Сохранение пользовательских настроек с помощью NSUserDefaults

Для хранения пользовательских настроек месжду запусками приложения в Cocoa имеется класс NSUserDefaults . Каждому приложению доступен общий экземпляр класса NSUserDefaults . Доступ к этум экземпляру осуществляется с помощью вызова статического метода standardUserDefaults:

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

NSUserDefaults может сохранять, в качестве значений параметров, основные типы: float , double , integer , boolean и объекты стандартных классов: NSData , NSString , NSNumber , NSDate , NSArray , NSDictionary . Объекты классов NSArray , NSDictionary также должны содержать только объекты перечисленных классов. Если необходимо сохранить объекты других типов, используйте метод archivedDataWithRootObject: класса NSKeyedArchiver для получения экземпляра класса NSData NSUserDefaults хранит значения в базе данных параметров пользователя. База данных создается автоматически для каждого пользователя. Для того, чтобы постоянно не дергать базу данных при чтении и изменении параметров, NSUserDefaults использует кэширование. NSUserDefaults возвращаемые неизменяемые объекты, даже если вы устанавливали изменяемый объект в качестве значения.

Получение экземпляра NSUserDefaults

Как было сказано выше, общий экземпляр класса NSUserDefaults возвращает метод standardUserDefaults: . Если экземпляр не был ранее создан, то метод создает его со списком поиска, который состоит из следующих доменов:

  • NSArgumentDomain, содержит параметры разобранные из аргументов приложения
  • Домен нашего приложения, состоящий из идинтифиатора пакета приложения (Bundle identifier). Например, если наш идентификатор ru.osxdev.testdefs, то и домен будет ru.osxdev.testdefs
  • NSGlobalDomain, содержит глобальные параметры доступные во всех приложениях
  • Отдельные домены для каждого из предпочтительных языков пользователя
  • NSRegistrationDomain, содержит временные параметры со значениями по умолчанию. Значения по умолчанию устанавливаются с помощью метода registerDefaults: . Параметры из этого домена не сохраняются физически на диск

Созданный объект инициализирован параметрами действительными только для текущего пользователя. Создать экземпляр класса также можно с помощью вызова методов alloc: и init: или initWithUser: :

Метод initWithUser: возвращает экземпляр объекта с параметрами для указанного пользователя. Метод возвращает nil, если нет доступа к указанной учетной записи. Этот метод полезно использовать в приложениях запускаемых суперпользователем и может быть использовано для обновления базы данных параметров для различных пользователей.

Регистрация параметров по умолчанию

В момент запуска приложения необходимо зарегистрировать значения по умолчанию для тех параметров, значения которых должны быть действительными в любом случае. Когда в приложении вы запросите значение параметра, которое не было ранее задано, NSUserDefaults вернет зарегистрированное значение по умолчанию. Регистрация значений по умолчанию осуществляется с помощью метода registerDefaults:dictionary

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

Сохранение параметров

Методы установки значений:

  • -setBool:forKey: - устанавливает логическое значение для заданного ключа
  • -setFloat:forKey: - устанавливает значение с плавающей точкой для заданного ключа
  • -setInteger:forKey: - устанавливает целочисленное значения для заданного ключа
  • -setObject:forKey: - устанавливает объект в качестве значения для заданного ключа. В качестве значения могут использоваться только объекты классов NSData , NSString , NSNumber , NSDate , NSArray и NSDictionary
  • -setDouble:forKey: - устанавливает значение с типом double для заданного ключа
  • -setURL:forKey: - устанавливает URL в качестве значения для указанного ключа. При сохранении экземпляра NSURL проводятся следующие модификации:
    • Экземпляры NSURL не являющиеся ссылками на файлы архивируются с помощью +[NSKeyedArchiver archivedDataWithRootObject:], в качестве корневого элемента в метод передается экземпляр NSURL . После этого сохраняемым значением параметра будет экземпляр класса NSData
    • Экземпляры NSURL содержащие ссылки на файл со схемой file: будут обрабатываться как не файловые ссылки, как это описано в первом пункте, но дополнительно в архиве будет сохранена информация которая делает эту ссылку совместимой с системами Mac OS X 10.5, а также минимальные bookmark данные
    • Для абсолютных путей на файлы в экземплярах NSURL со схемой file: будет предпринята попытка конвертировать путь на файл относительно домашнего каталога пользователя. Если это возможно, то в качестве значения будет записана строка, полученная с помощью вызова метода stringByAddingPercentEscapesUsingEncoding : экземпляра NSURL

    Пример сохранения параметров:

    Чтение параметров

    Методы чтения значений:

    • -arrayForKey: - возвращает массив ассоциированный с указанным ключом. Метод вернет nil, если ключ не найден или ассоциированные с этим ключом данные не являются объектом класса NSArray
    • -boolForKey: - если логическое значение связано с указанным ключом, это значение будет возвращено. Иначе метод вернет NO
    • -dataForKey: - возвращает объект класса NSData ассоциированный с указанным ключом. Метод вернет nil, если ключ не найден или ассоциированные с этим ключом данные не являются объектом класса NSData
    • -dictionaryForKey: - возвращает словарь ассоциированный с указанным ключом. Метод вернет nil, если ключ не найден или ассоциированные с этим ключом данные не являются объектом класса NSArray
    • -floatForKey: - возвращает значение с плавающей точкой ассоциированное с указанным ключом. Метод вернет 0, если ключ не найден
    • -integerForKey:defaultName - возвращает целочисленное значение (NSInteger) ассоциированное с указанным ключом. Метод вернет 0, если указанный ключ не найден
    • -objectForKey:defaultName - возвращает объект ассоциированный с указанным ключом. Метод вернет nil, ели ключ не найден
    • -stringArrayForKey:defaultName - возвращает массив строк ассоциированный с указанным ключом. Метод вернет nil, ели ключ не найден, значение не является объектом класса NSArray или массив не содержит объекты NSString
    • -stringForKey:defaultName - возвращает строку ассоциированную с указанным ключом. Метод вернет nil, ели ключ не найден или значение не является объектом класса NSString
    • -doubleForKey:defaultName - возвращает double значение ассоциированное с указанным ключом. Метод вернет 0, если ключ не найден
    • -URLForKey:defaultName - возвращает объект класса NSURL ассоциированный с указанным ключом. Метод вернет nil, если ключ не найден. В методе при считывании значения используется следующая логика:
      • Если значение ассоциированное с указанным ключом является объектом класса NSData , то этот объект используется в качестве аргумента метода unarchiveObjectWithData: ([NSKeyedUnarchiver:unarchiveObjectWithData]). Если объект класса NSData может быть разархивирован как NSURL , то метод вернет объект класса NSURL , в противном случае метод вернет nil.
      • Если ассоциированное с ключом значение является ссылкой на файл, будет создана объект класса NSURL с ссылкой на файл, но его bookmark данные не будут зарезолвлены, пока объект не будет использован
      • Если ассоциированное с ключом значением является строкой, начинающейся с символа

      Поиск значений осуществляется в доменах списка поиска в порядке в котором они были добавлены в список. Получить все параметры из всех доменов поиска можно вызвав метод dictionaryRepresentation: . Метод возвращает словарь со всеми параметрами.

      Пример чтения параметров:

      Удаление параметров

      Удаление параметров осуществляется с помощью метода removeObjectForKey: . Метод принимает единственный аргумент - название ключа.

      Синхронизация

      Синхронизация данных, хранящихся в кэше, с данными, хранящимися в базе данных параметров, происходит автоматически с определенными временными интервалами. Если данные необходимо синхронизировать немедленно, не дожидаясь пока это произойдет автоматически, необходимо вызвать метод synchronize :. Метод вернет YES , если данные были успешно синхронизированы, иначе NO .

      Управление доменами

      Домены разделяются на постоянные и не постоянные. Постоянные домены существуют между вызовами приложения. Непостоянные домены не сохраняются между вызовами приложения. Например, постоянным доменам являются NSGlobalDomain , домен равный идентификатору вашего приложения, а непостоянным - NSRegistrationDomain , NSArgumentDomain . Методы управления параметрами связанными с постоянными доменами:

      • -persistentDomainNames - возвращает массив строк с названиями текущих постоянных доменов
      • -persistentDomainForName - возвращает словарь с ключами и значениями параметров для постоянного домена, название которого было указано
      • -removePersistentDomainForName - удаляет все параметры связанные с указанным постоянным доменном
      • -setPersistentDomain:forName: - устанавливает параметры, переданные в словаре, в указанный постоянный домен. Название домена должно быть равным идентификатору пакета приложения (Bundle identifier)

      Методы управления параметрами связанными с непостоянными доменами:

      • -volatileDomainNames - возвращает массив строк с названиями текущих непостоянных доменов
      • -volatileDomainForName - возвращает словарь с ключами и значениями параметров для непостоянного домена, название которого было указано
      • -removeVolatileDomainForName - удаляет все параметры связанные с указанным непостоянным доменном
      • -setVolatileDomain:forName: - устанавливает параметры, переданные в словаре, в указанный непостоянный домен

      NSUserDefaults также позволяет использовать установленные параметры между приложениями. Если вам необходимо из приложения B получить доступ к параметрам приложения A, то в приложение B, в список поиска, вам необходимо добавить домен приложения A. Делается это с помощью метода addSuiteNamed: . Данные связанные с добавленным доменом доступны только для чтения. Метод принимает в качестве аргумента название домена. Обычно это идентификатор приложения. Для примера в своем приложении мы можем получить пути к базам данных iTunes:

      Удалить домен из списка поиска можно с помощью метода removeSuiteNamed: . Метод принимает в качестве аргумента название удаляемого из списка поиска домена.

      Уведомления

      NSUserDefault посылает уведомление NSUserDefaultsDidChangeNotification когда происходит изменение значения параметра в постоянном домене. Объект уведомления - NSUserDefaults . Уведомление не содержит словарь userInfo. Пример использования уведомления: