it-swarm.com.ru

iOS 10 с XCode 8 GM вызвал NSUserDefaults периодически не работает

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

Моя проблема другая, так как я могу воспроизвести это на Objective 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.

EDITОшибка записана: 28287988

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

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

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

17
Pranoy C

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

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

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

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

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

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

9
nugae

Аналогичный очень умный DTS ответ на мой собственный запрос в службу поддержки. По сути, убийство с использованием XCode является более смертоносным, чем все, что обычно происходит на устройстве (даже метод двойного щелчка по домику и метод upswipe), и, поскольку все внезапно падает, когда XCode останавливает его, ленивая запись NSUserDefaults может завершиться неудачей, или быть только наполовину завершено.

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

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

0
nugae