Подтвердить что ты не робот

Как отлаживать/обрабатывать прерывистые ошибки "авторизации отказано" и "диск i/o" при добавлении хранилища SQL в NSPersistentStoreCoordinator?

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

Что происходит в этих сбоях, следующее:

  • Приложение запускает и инициализирует стек Core Data​​p >

  • Приложение пытается добавить хранилище SQL в NSPersistentStoreCoordinator со следующим кодом (storeURL):

    NSDictionary *options = @{
        NSMigratePersistentStoresAutomaticallyOption : @(YES),
        NSInferMappingModelAutomaticallyOption : @(YES)
    };
    
    sqlStore = [_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                                                         configuration:nil
                                                                   URL:storeURL
                                                               options:options
                                                             error:&error];
    
  • При добавлении этого хранилища возникает одна из следующих ошибок:

NSError:

Домен = NSCocoaErrorDomain
  Код = 256" Операция не может быть выполнена. (Cocoa ошибка 256.) "
  UserInfo = 0x1dd946a0 {NSUnderlyingException = отказ авторизации, NSSQLiteErrorDomain = 23}

или

NSError:

Домен = NSCocoaErrorDomain
  Код = 256" Операция не может быть выполнена. (Cocoa ошибка 256.) "
  UserInfo = 0xc6525d0 {NSUnderlyingException = ошибка ввода-вывода диска, NSSQLiteErrorDomain = 10}

После этого условия приложение столкнется с ошибкой b/c для работы приложения требуется хранилище SQL. Я мог бы попытаться изящно справиться с этим сбоем, попробовав новый storeURL, но я не хочу, чтобы пользователь потерял существующие данные. Кроме того, я никогда лично не воспроизводил эту проблему и не основывался на низком числе пользователей, затронутых и разбитых журналах. Я считаю, что это проблема с низким уровнем воздействия и не повторяется при последующем запуске приложения.

Я надеюсь, что там есть гуру Core Data с некоторыми предложениями относительно того, как отлаживать и предотвращать/обрабатывать эти условия. Мой основной код инициализации стека данных прямо из генератора проекта xcode, и я исключил проблемы concurrency в том, что постоянный координатор хранилища инициализируется только один раз (при запуске), и эта ошибка возникает в этой инициализации.

С удовольствием предоставляем больше кода/информации, если это необходимо.

спасибо!

4b9b3361

Ответ 1

Похоже, что XJones и я смогли найти причину этого. Похоже, что это ошибка iOS с красным регистром или недокументированное поведение. Я подал это под Apple ошибка ID 12935031.

Неисправный сценарий, когда приложение, использующее существенное изменение местоположения основного местоположения или мониторинг региона, может не запускаться должным образом (или иметь другие непредвиденные последствия) из-за того, что с iOS 5 хранилища Core Data используют защиту данных ( шифрование) по умолчанию.

Шаги по воспроизведению:

1) Включите защиту защитного кода на устройстве

2) Создайте приложение, которое запустит "Мониторинг значимого местоположения" или "Мониторинг регионов" и продолжит его работу даже в фоновом режиме. То есть. Приложение, которое использует фоновое значительное изменение местоположения или мониторинг региона.

3) Дождитесь окончания работы батареи на устройстве (могут быть и другие причины)

4) Устройство выключится

5) Подключите устройство к Mac

6) Как только заряд будет достаточным, устройство загрузится. Важно: не отключайте устройство в это время.

7) Выход или вход в контролируемый диапазон или возникновение значительного изменения местоположения. Теперь устройство автоматически перезапустит приложение, так как оно зарегистрировано для мониторинга значимого местоположения или мониторинга региона.

8) Однако, поскольку устройство не было разблокировано пользователем (код доступа еще не введен), приложение не сможет прочитать ни один из защищенных файлов данных. В приложении "Основные данные" это приведет к тому, что постоянный координатор хранилища не сможет добавить файл постоянного хранилища в контекст управляемого объекта. Это приведет к сбою приложения или в зависимости от кода, используемого разработчиком, даже попытку reset базы данных. В других приложениях это может привести к сбоям по другим причинам, так как это непредвиденный недокументированный побочный эффект включенной функции защиты данных по умолчанию для хранилищ Core Data в iOS 5 и более поздних версиях.

Решение или обходной путь до тех пор, пока Apple не исправит это или, по крайней мере, документы, чтобы убедиться, что ваше приложение перестает отслеживать значительные изменения/регионы региона в приложенииWillTerminate или , чтобы отключить функцию защиты данных по умолчанию, установив NSFileProtectionNone для NSFileProtectionKey введите ключ словаря при добавлении хранилища основных данных в постоянный координатор хранилища., чтобы дождаться, когда хранилище файлов станет доступным, используя цикл while(), который проверяет доступность защищенных данных. Могут быть другие способы сделать это с помощью KVO, но этот метод работает надежно и проще всего вставлять в существующий код, не перерабатывая весь процесс запуска приложения.

Обновление: похоже, просто установить этот ключ недостаточно, если защита данных уже активна в хранилище. Вы должны вручную установить его:

[[NSFileManager defaultManager] setAttributes:[NSDictionary dictionaryWithObject:NSFileProtectionNone forKey:NSFileProtectionKey] ofItemAtPath:storePath error:nil];

Забастовкa > код >

Здесь исправление для приложений, которым необходим мониторинг фонового местоположения, благодаря большему количеству запросов от XJones и немного больше исследований в Apple, разбросанных документах:

while(![[UIApplication sharedApplication] isProtectedDataAvailable]) {
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.5f]];
}

код >

Этот код идет до того, как вы попытаетесь добавить файл данных хранилища в постоянный координатор хранилища.

Обновление 2015: Вы также можете установить NSPersistentStoreFileProtectionKey в NSFileProtectionNone. Это будет правильно отключать защиту файлов (если вам это не нужно) и просто работать без каких-либо обходных решений. Причина, по которой он не работал в предыдущих попытках, состоит в том, что ключ словаря, который я тестировал, был неправильным.

Ответ 2

Я только заметил следующие уведомления в документах UIApplication:

UIApplicationProtectedDataDidBecomeAvailable UIApplicationProtectedDataWillBecomeUnavailable

Они доступны в iOS 4.0 и более поздних версиях. @lupinglade, я думаю, вам нужно наблюдать за этими уведомлениями и получать доступ к защищенным файлам (т.е. магазину) после получения UIApplicationProtectedDataDidBecomeAvailable.

Ответ 3

Решение @lupinglade в значительной степени работало в моем случае (приложение VoIP при запуске после перезагрузки), но я также хотел бы отметить, что существует функция делегата для AppDelegate, которая вызывается, когда защищенные данные становятся доступными:

applicationProtectedDataDidBecomeAvailable:

Это облегчило реализацию решения в моем случае.

В соответствии с файлом заголовка он доступен с iOS 4 и далее.

Ответ 4

Такая же проблема здесь, тем не менее, не смогла найти решение. Я обнаружил, что это похоже на наличие кода блокировки, установленного на устройстве. С кодом блокировки я никогда не мог воспроизвести ошибку, теперь я смог кучу раз. Журнал консоли:

Ошибка: Error Domain = NSCocoaErrorDomain Code = 256 "Операция не может быть выполнена. (Cocoa ошибка 256.)" UserInfo = 0x1fd80110 {NSUnderlyingException = авторизация denied, NSSQLiteErrorDomain = 23}

Файл существует и не использует никакого шифрования.