Сбой основных данных «Внешняя ссылка на данные не может найти базовый файл».

#ios #swift #xcode #encryption #core-data

Вопрос:

В приложении есть хранилище CoreData, где (помимо других данных) могут храниться изображения. Поскольку изображения могут быть разных размеров, эта Allows External Storage настройка включена.

Иногда приложение рушится с ошибкой, указанной в названии:

Исключение NSInternalInconsistencyException Внешняя ссылка на данные не может найти базовый файл.

Это происходит только в выпущенном приложении, только для некоторой доли пользователей. Я никогда не мог воспроизвести его (установка Optimization level в Fastest, Smallest [-Os] значение также не помогла в воспроизведении).

Что видно из часового (используется для сообщения о сбоях):

  • это происходит, когда приложение пытается извлечь объект из основных данных; объект обладает data свойством, которое является изображением, и у Allows External Storage него включена настройка
  • это происходит, когда приложение находится в фоновом режиме (обычно более пары минут, но может произойти и быстрее).
  • его нет в основном потоке.

Чтобы разрешить доступ к хранилищу из разных потоков, было реализовано следующее:

 private var context: NSManagedObjectContext {
        if Thread.current.isMainThread {
            return persistentContainer.viewContext
        }
        return backgroundContext // this is initialised once with persistentContainer.newBackgroundContext()
 }
 

Еще одна потенциально полезная информация заключается в том, что для основных данных включена защита:

 // encrypt core data contents
// FileProtectionType.complete means that core data contents will be encrypted at all times when the device is locked
container.persistentStoreDescriptions.forEach {
     $0.setOption(FileProtectionType.complete as NSObject, forKey: NSPersistentStoreFileProtectionKey)
}
 

Любая помощь в отношении идей о том, как исправить эту ошибку, будет более чем приветствоваться.
Заранее спасибо.

Комментарии:

1. Не совсем уверен, что понимаю, зачем вам нужна context реализация, которая возвращает либо контекст просмотра, либо фоновый контекст. Вы можете использовать контекст просмотра напрямую без диспетчерской работы с perform учетом того, что вы находитесь в основном потоке, однако для фонового контекста вам всегда нужно использовать perform , поскольку невозможно сделать предположение о текущем контексте (очередь/поток). Также поддерживается поддержка постоянных контейнеров performBackgroundTask . Так что, возможно, виноват в том, как вы взаимодействуете с контекстами. У меня не так много кода для просмотра, так что просто подкидываю несколько идей.

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

3. Это не то, как параллелизм работает с основными данными. Если вы используете выделенную очередь, а не perform или performAndWait (или performBackgroundTask ), то вы настраиваете себя на проблемы параллелизма. Core Data не заботится о вашей выделенной очереди, только о своих собственных очередях.

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

5. Выдержка из документации: Core Data uses thread (or serialized queue) confinement to protect managed objects and managed object contexts (see Core Data Programming Guide). A consequence of this is that a context assumes the default owner is the thread or queue that creates it. Don’t, therefore, initialize a context on one thread then pass it to another. В любом случае я бы предложил использовать perform или performAndWait . Я вижу, как проблемы с параллелизмом могут привести к несогласованному состоянию, особенно когда дело доходит до хранения файлов на диске.