IOS 10 с XCode 8 GM заставил NSUserDefaults прерывисто работать

ПРИМЕЧАНИЕ: Я видел много других сообщений о переполнении стека о NSUserDefaults, которые были переименованы в UserDefaults в Swift или не работают на симуляторе до перезапуска. В любом случае это не дубликат. Многие вопросы, на которые ссылаются теги, - это 4 года назад. Мой вопрос специфичен для iOS 10 с этого года, поскольку он всегда работал в более старых версиях. Я уже упоминал в своем вопросе, что мой вопрос не является дубликатом этих вопросов, так как это были ошибки симулятора в swift, и моя проблема связана с ошибкой объекта C. Пожалуйста, прочитайте вопросы перед тем, как пометить их как дубликаты

Моя проблема отличается, поскольку я могу воспроизвести это на объективе C и на самом физическом устройстве.

Я создал совершенно новый проект с нуля для этого теста. Я разместил этот код в viewDidLoad контроллера вида:

if (![[NSUserDefaults standardUserDefaults] valueForKey:@"checkIfInitialized"]){
    NSLog(@"setting checkIfInitialized as not exist");
    [[NSUserDefaults standardUserDefaults] setValue:@"test" forKey:@"checkIfInitialized"];
    [[NSUserDefaults standardUserDefaults] synchronize];
    self.view.backgroundColor=[UIColor redColor];
    [email protected]"NSUserDefaults was NOT there, try running again";
} else {
    NSLog(@"checkIfInitialized exists already");
    self.view.backgroundColor=[UIColor blueColor];
    [email protected]"NSUserDefaults was already there this time, try running again";
}

Теперь, если я запустил приложение примерно 10 раз, несколько раз он находит checkIfInitialized, а иногда нет. Нет точного числа, сколько раз он терпит неудачу, так как он может работать 3 раза, а затем проваливаться через 2 раза, затем работать 4 раза и терпеть неудачу один раз и т.д.

Теперь что-то, что я заметил (не уверенно на 100%), что проблема возникает, только когда я тестирую подключение через Xcode. Если я запустил приложение, щелкнув значок приложения на устройстве без Xcode, тогда он работает нормально, но я не могу быть на 100% уверенным.

Я заметил, что эта ошибка возникает иногда:

[User Defaults] Failed to write value for key checkIfInitialized in CFPrefsPlistSource<0x1700f7200> (Domain: com.xxxx.appname, User: kCFPreferencesCurrentUser, ByHost: No, Container: (null)): Path not accessible, switching to read-only

У меня есть этот очень простой проект на моем Dropbox, если вы хотите проверить его. Я бы предложил тестирование примерно 10-15 раз, чтобы воспроизвести эту проблему.

https://www.dropbox.com/s/j7vbgl6e15s57ix/nsuserdefaultbug.zip?dl=0

Это отлично работает на iOS 9, что определенно связано с iOS 10.

ИЗМЕНИТЬ Ошибка: 28287988

Ответ от команды Apple DTS:

Прежде всего, вы должны сначала определить, являются ли стандартнымиUserDefaults или ЗначениеForKey не работает. Я предполагаю, что "standardUserDefaults" возвращая NULL, и если это так, то это то, что вы должны быть защищены от общего. Примечательно, что standardUserDefaults вернет NULL, если файл предпочтения зашифрован в среда, в которой в настоящее время работает приложение (например, предпочтения установлено значение "NSFileProtectionComplete", и приложение запускается в задний план). Это не должно быть проблемой для стандартного переднего плана приложений, но это то, что нужно знать в любом случае.

Скорее всего, Xcode фактически вызывает проблему здесь. Xcode значительно усложняет среду запуска приложения таким образом, что ОЧЕНЬ отличается от стандартного запуска приложения. Я предполагаю, что это в основном, инициируется синхронизацией Xcodes, вызывая ожидаемый ситуации во время запуска приложения, но если вы хотите более формальный тест которые пытаются установить единую точку останова в applicationDidFinishLaunching и продолжать в отладчике, как только вы его ударили. Мое предположение просто добавляя, что нарушает время, достаточное, чтобы остановить проблему из происходит. Вроде. Его iOS 10 только в том смысле, что iOS 9 никогда не печатайте это сообщение журнала, но это потому, что сообщение журнала было добавлен в iOS 10. Сам код достаточно похож на iOS 9.3, что я подозревают, что такое же поведение (по крайней мере теоретически) возможно в iOS 9.

Ответы

Ответ 1

Да, это определенно воспроизводимая ошибка.

  • Это происходит с выпуском GM Xcode 8 и iOS 10.
  • не связанный вопрос со ссылкой на Swift.
  • Это не связанный вопрос, относящийся к бета-версиям симулятора.

Ошибка происходит на устройствах и на симуляторе. Это прерывисто: сохранение будет работать шесть раз, а затем сбой. В отличие от вас, я не получил сообщение "не удалось написать ключ".

Ошибка также возникает при работе непосредственно на устройстве без Xcode. Это на самом деле то, как я его обнаружил.

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

Одно ключевое различие: В моем случае ошибка записывается по умолчанию. Ранее записанное значение остается в NSUserDefaults. Иногда один ключ успешно записывается, а другой не изменяется.

Ответ 2

Аналогично очень интеллектуальный ответ DTS из моего собственного запроса поддержки. В принципе, убийство с использованием Xcode более убийственно, чем что-либо, что, естественно, произойдет на устройстве (даже метод с двойным нажатием кнопки "вверх" и "вверх-вниз" ), и поскольку все внезапно разбивается, когда Xcode останавливает его, ленивая запись NSUserDefaults может завершиться неудачей, или быть только наполовину завершенным.

И действительно, чистое тестирование устройства на устройстве без участия Xcode показывает, что все правильно записывается в NSUserDefaults, когда приложение завершается.

Я закрыл свой собственный отчет об ошибке.