Когда (не) злоупотреблять NSUserDefaults - PullRequest
23 голосов
/ 02 апреля 2011

Интересно, для чего предназначены инструкции:
1 - как часто я могу читать из NSUserDefaults
2 - сколько данных я могу разумно хранить в NSUserDefaults

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

Некоторые примеры среди других:

  • Если в моей игре есть возможность, чтобы компьютер был одним из игроков, я буду использовать NSUserDefaults для сохранения этого логического значения. Это очень ясно. Но также имеет ли смысл обращаться к NSUserDefaults во время моей игры каждый раз, когда я хочу узнать, является ли компьютер игроком, или я должен вместо этого использовать переменную экземпляра? Предположим, здесь мне нужно проверять это логическое значение каждую секунду. Ответ тот же: вместо 100 мс? Как насчет каждые 10 с?

  • Если в моей игре 50 движущихся объектов и я хочу, чтобы их позиции и скорости сохранялись при выходе пользователя из приложения, является ли NSUserDefaults разумным местом для хранения этих данных? Как насчет 20 движущихся объектов? А как насчет 200?

Ответы [ 5 ]

16 голосов
/ 02 апреля 2011

Интересно, для чего это руководство: 1 - как часто я могу читать из NSUserDefaults

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

2 - сколько данных я могу разумно хранить в NSUserDefaults

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

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

просто добавьте const bool к объекту противника. нулевая потеря времени выполнения, кроме памяти, которая не будет существенной.

Предположим, мне нужно проверять это логическое значение каждую секунду. Ответ тот же: вместо 100 мс? Как насчет каждые 10 с?

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

Если в моей игре 50 движущихся объектов, и я хочу, чтобы их позиции и скорости сохранялись при выходе из приложения, является ли NSUserDefaults разумным местом для хранения этих данных? Как насчет 20 движущихся объектов? Как насчет 200?

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

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

14 голосов
/ 02 апреля 2011

Не беспокойтесь об ограничениях.Вместо этого задайте себе этот простой вопрос:

Это предпочтение?

Если это предпочтение, то оно должно быть в пользовательских значениях по умолчанию.Вот для чего нужны пользовательские настройки по умолчанию.Если нет, то он должен находиться в каталоге «Документы» (или на Mac, возможно, в разделе «Поддержка приложений»).

В iOS вы можете указать, является ли это предпочтением или нет, по тому, будет ли это целесообразноесли возможно) поместите его в свой комплект настроек для отображения и редактирования в приложении «Настройки».В Mac OS X вы обычно можете определить, является ли это предпочтением или нет, по тому, что было бы целесообразно поместить его в окне настроек.

Конечно, это зависит от вашего суждения.Например, Stanza для Mac ошибается, помещая не предпочтения в окно настроек.

Вы также можете рассмотреть вопрос по его обратному вопросу:

Создан ли он пользователемdata?

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

10 голосов
/ 02 апреля 2011

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

Тем не менее, NSUserDefaults использует кэш в памяти, а стоимость составляет всегопонесено при синхронизации.Согласно документации, синхронизация происходит «автоматически… через определенные промежутки времени»;Я полагаю, что это применимо только в том случае, если что-то изменилось.

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

7 голосов
/ 02 апреля 2011

В NSUserDefaults можно использовать от сотен до тысяч элементов (в основном это просто оболочка для сериализации списка свойств). Что касается накладных расходов для вашего приложения, лучше всего попробовать его и использовать профилировщик.

2 голосов
/ 14 июля 2012

NSUserDefaults - это, в основном, оболочка для загрузки NSDictionary из файла .plist с диска (а также для записи его на диск). Вы можете хранить столько данных в NSUserDefaults, но у вас мало контроля над тем, сколько памяти он использует, и как он читает с диска.

Я бы использовал разные технологии для разной информации / данных.

  • Небольшие биты данных с серверов, предпочтений, информации о пользователях и так далее, я бы использовал NSUserDefaults.

  • Для информации о входе в систему (токены доступа, конфиденциальные данные) я бы использовал цепочку для ключей. Брелок также можно использовать для данных, которые не следует удалять при удалении приложения.

  • Для больших объемов серверных данных или игровых данных я бы записал их на диск, но сохранил в памяти.

В вашей ситуации я бы держал его в памяти (вероятно, @property), но я бы периодически записывал его на диск (возможно, каждые 1-5 раз, когда он меняется, используйте int ivar). Убедитесь, что этот метод записи на диск находится в AppDelegate, чтобы он не завершился ошибкой при закрытии контроллера представления, который его выполняет.

Таким образом, данные легко доступны, но также сохраняются на диск для безопасного хранения.

...