Помните об этом случае, когда ваше приложение работает в фоновом режиме и вы не можете получить доступ к своим сохраненным значениям в NSUserDefaults:
По этому поводу было много потоков и ошибок, но это снова происходит со мной в ios 9. У меня есть приложение, которое запускается в фоновом режиме в ответ на задачи NSURLSession и толчки с доступным содержимым. Воспроизводимо, если я перезагружаю свой телефон и жду фонового запуска моего приложения, тогда, когда я открываю приложение, я обнаруживаю, что [[NSUserDefaults standardUserDefaults] dictionaryRepresentation] содержит все системные значения, например AppleITunesStoreItemKinds и т. Д., Но не содержит любое из установленных мной значений. Если я выйду принудительно и перезапущу приложение, все мои значения вернутся. Есть ли способ избежать кэширования «пустых» значений standardUserDefaults до разблокировки телефона или, по крайней мере, определить, когда они испорчены, и исправить их без принудительного выхода из приложения?
Проблема здесь в том, что NSUserDefaults в конечном итоге поддерживается файлом в контейнере вашего приложения, а контейнер вашего приложения подлежит защите данных. Если вы ничего особенного не сделаете, то в iOS 7 и новее ваш контейнер использует NSFileProtectionCompleteUntilFirstUserAuthentication, значение, которое наследуется резервным хранилищем NSUserDefaults, и поэтому вы не можете получить к нему доступ до первой разблокировки.
IMO лучший способ обойти это - избегать NSUserDefaults для вещей, на которые вы полагаетесь в путях кода, которые могут выполняться в фоновом режиме. Вместо этого сохраните эти настройки в своем собственном файле настроек, в котором вы можете явно управлять защитой данных (в данном случае это означает «установить NSFileProtectionNone»).
Есть две проблемы с NSUserDefaults в контексте защиты данных:
Это полностью абстрактный API: наличие и расположение его резервного хранилища не считается частью этого API, поэтому вы не можете явно управлять его защитой данных.
Примечание. В последних версиях OS X NSUserDefaults управляется демоном, и люди, которые пытаются напрямую управлять его резервным хранилищем, сталкиваются с проблемами. Легко представить, что в какой-то момент подобное произойдет и с iOS.
Даже если бы изменение защиты данных было возможно, NSUserDefaults не имеет механизма для классификации данных на основе контекста, в котором вы их используете; это API "все или ничего". В вашем случае вы не хотите снимать защиту со всех своих пользовательских настроек по умолчанию, а только с тех, к которым вам нужно получить доступ в фоновом режиме перед первой разблокировкой.
Наконец, если какие-либо из этих данных действительно конфиденциальны, вы должны поместить их в связку ключей. Примечательно, что связка ключей действительно имеет возможность настраивать защиту данных для каждого элемента.