Каковы ограничения NSUserDefaults?

постоянное хранение данных в iPhone обычно выполняется с использованием Core Data или sqlite3. Большинство людей предпочитают использовать NSUserDefaults как хранилище для предпочтений приложений, а не как обычную базу данных (например, sqlite).

Я обнаружил, что большой объем данных может храниться в NSUserDefaults, он чрезвычайно прост в использовании и быстр. Так почему бы не использовать это как постоянное хранилище? Каковы ограничения NSUserDefaults как база данных?

обновление:
Я часто использую три разных способа сохранения данных на диск.

  • основные данные
  • сериализация объектов в plists
  • NSUserDefaults

Я больше не использую FMDB (или SQLite напрямую). Каковы основные преимущества и недостатки каждого подхода?

некоторые преимущества NSUserDefaults, с которыми я столкнулся:

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

4 ответов


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

в противном случае я нашел основные данные превосходящими во всех отношениях. Особенно в отношении настройки значений по умолчанию и процедур миграции.

Edit: как оказалось, NSUserDefaults "thread-safeness", похоже, происходит от выполнения операций над основным потоком. Это вызвало серьезный пропуск кадров в одном из моих приложений; я закончил тем, что вырвал NSUserDefaults и заменил его потокобезопасный NSMutableDictionary, который сериализуется в файл.


Sqlite3 более полезен для хранения большой базы данных и доступа к элементам базы данных. Вы можете сортировать элементы базы данных Sqlite3, вы можете очень быстро искать элемент в dtabase Sqlite3. База данных Sqlite3 имеет много привилегий, которые NSUserDefaults не было !


NSUserDefaults vs Sqlite3

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

вы не увидите разницы в скорости, но все равно лучше выбрать правильный механизм для того, что вы делаете. Если это просто предпочтения, используйте NSUserDefaults, иначе я бы сериализовал ваши объекты в plist. Если вы новичок в Cocoa, я бы сначала избегал основных данных и даже Sqlite, чтобы дать себе шанс изучить основы первый.


NSUserDefaults или Sqlite

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


использование NSUserDefaults для сохранения большого количества игровых данных

обычно NSUserDefaults используется для сохранения настроек игры. Чтобы сохранить данные игры, это обычно лучше использовать SQLite или вы можете создать NSDictionary объектов и сохранить на диск, здесь пара сообщений, которые могут помочь:

  1. http://www.cocos2d-iphone.org/forum/topic/9308
  2. http://www.cocos2d-iphone.org/forum/topic/9210

для проекта, над которым я сейчас работаю, мне нужно настроить большую базу данных (около 400.000 записей). При использовании NSUserDefaults необходимо добавить записи, которые могут занять до нескольких минут (в зависимости от устройства и способа импорта данных). Если вы используете CoreData, вы просто можете скопировать предварительно созданную базу данных в каталог документов вашего приложения и использовать ее немедленно.

вот почему я полагаюсь на CoreData.


одним из преимуществ CoreData является то, что ваш объект будет NSManagedObject со свойствами. Это означает, что при получении или установке значений у вас будет автозаполнение, чтобы помочь вам с именами свойств. Это также делает код более читаемым.

между тем с NSUserDefaults вы должны всегда использовать методы доступа key-value, используя строки для ключа.

то есть:

myGlobalSettingsObject.lastLoginTime = @(now);

и

[[NSUserDefaults standardUserDefaults] setValue:@(now) forKey:@"lastLoginTime"];

Что делать, если вы случайно сделать опечатку в установке ключа где-то? Компилятор не предупредит вас. Что, если кто-то где-то ставит не тот тип? Компилятор не предупредит вас.

например:

[[NSUserDefaults standardUserDefaults] setValue:@"now" forKey:@"lastLoginTiem"]; ^ ^ ^^^^

... приведет ни предупреждения, ни ошибки во время сборки... опасно!

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

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

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