Сохранение пользовательских настроек с помощью 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. Пример использования уведомления: