macOS High Sierra 10.13 — Core Data — NSColor перестает работать как трансформируемый атрибут

После обновления до macOS High Sierra 10.13 и Xcode 9 существующее работающее приложение Cocoa с настройками приложения на основе документов и использования основных данных перестало работать.

Проблема в том, что мое приложение перестало открывать свои файлы документов с исключением:

[error] error: -addPersistentStoreWithType:Binary configuration:(null) URL:file:///Users/xxx/Library/Autosave%20Information/Unsaved%20zzz%20Document%202.binary options:{
    NSPersistentStoreRemoveStoreOnCleanup = 1;
} ... returned error Error Domain=NSCocoaErrorDomain Code=259 "The file couldn’t be opened because it isn’t in the correct format." UserInfo={NSUnderlyingException=Can't read binary data from file, NSUnderlyingError=0x60c00005ff20 {Error Domain=NSCocoaErrorDomain Code=259 "The file “Unsaved zzz Document 2.binary” couldn’t be opened because it isn’t in the correct format." UserInfo={NSFilePath=/Users/tora/Library/Autosave Information/Unsaved zzz Document 2.binary, NSUnderlyingException=value for key 'NS.objects' was of unexpected class 'NSColor'. Allowed classes are '{(
    NSDictionary,
    NSDictionaryMapNode,
    NSArray,
    NSString,
    NSNumber,
    NSOrderedSet,
    NSCalendarDate,
    NSDate,
    NSSet,
    NSDecimalNumber,
    NSUUID,
    NSNull,
    NSURL,
    NSData
)}'.}}} with userInfo dictionary {

(omit)

Это приложение использует NSColor, а также Boolean, Integer 32, Double в файле Document.xcdatamodeld. Тип NSColor указан как Transformable, который обрабатывается с помощью NSArchiver для кодирования и NSUarchiver для декодирования через производный класс ValueTransformer.

Временное решение:

Согласно сообщению Джорджа Брауна, macOS High Sierra сделала декодирование данных объекта более безопасным. iOS 11 — Core Data — UIColor больше не работает как трансформируемый атрибут

Благодаря его решению переопределение configurePersistentStoreCoordinator решает эту проблему.

class Document: NSPersistentDocument {

  override func configurePersistentStoreCoordinator(for url: URL, ofType fileType: String, modelConfiguration configuration: String?, storeOptions: [String : Any]? = nil) throws {

    var options: [String : Any] = storeOptions ?? [:]

    if #available(OSX 10.13, *) {
      let accepted_classes: NSSet = [ NSColor.self ]
      options[NSBinaryStoreSecureDecodingClasses] = accepted_classes
    }

    do {
      try super.configurePersistentStoreCoordinator(for: url, ofType: fileType, modelConfiguration: configuration, storeOptions: options)
    }
    catch let e {
      throw e
    }
  }

}

Пожалуйста, расскажите нам о ваших блестящих способах!

Отредактировано:

К сожалению, одно из решений в Swift уже было опубликовано Wizard of Kneup на stackoverflow.com. Это в самом конце поста Джорджа Брауна.

Я увидел еще один, неполный пост Джорджа Брауна и попытался решить сам. https://reformatcode.com/code/objective-c/ios-11---core-data---uicolor-no-longers-works-as-transformable-attribute

Я должен был найти сообщение Wizard of Kneup до моей попытки.

Спасибо Джорджу Брауну и Wizard of Kneup!


person Tora    schedule 21.10.2017    source источник
comment
У меня возникают проблемы при попытке сохранить как. configurePersistentStoreCoordinator даже не вызывается. Вместо этого снова появляется та же ошибка. Есть идеи?   -  person Wizard of Kneup    schedule 15.02.2018
comment
Wizard of Kneup, я только что попробовал и обнаружил, как вы упомянули, configurePersistentStoreCoordinator не вызывается, когда saveDocumentAs: реализовано с самого начала в NSDocument, выполняется через меню. Но в моем случае ошибок не было. Хм. Затем, Open Recent сохраненный файл, вызывается Координатор. Обратите внимание, что NSDocument, кажется, скрывает пункт меню Save As... и добавляет Duplicate. Я вручную добавил привязку Save As For Test... к saveDocumentAs: для воспроизведения. Протестировано с Xcode 9.2.   -  person Tora    schedule 16.02.2018
comment
Целью configurePersistentStoreCoordinator, насколько я понимаю, является защита приложения от вредоносных файлов, пытающихся внедрить экземпляры вредоносного класса. Таким образом, он должен вызываться при открытии файлов, но при сохранении документа в файл его вызывать не нужно. Я знаю, что ты это уже знаешь. Дело может быть в том, почему ошибка возникает, когда saveAs.   -  person Tora    schedule 16.02.2018
comment
Приведенное выше обсуждение будет продолжено на stackoverflow.com /вопросы/48699000/   -  person Tora    schedule 16.02.2018