После обновления до 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!
configurePersistentStoreCoordinator
не вызывается, когдаsaveDocumentAs:
реализовано с самого начала вNSDocument
, выполняется через меню. Но в моем случае ошибок не было. Хм. Затем,Open Recent
сохраненный файл, вызывается Координатор. Обратите внимание, чтоNSDocument
, кажется, скрывает пункт менюSave As...
и добавляетDuplicate
. Я вручную добавил привязкуSave As For Test...
кsaveDocumentAs:
для воспроизведения. Протестировано с Xcode 9.2. - person Tora   schedule 16.02.2018configurePersistentStoreCoordinator
, насколько я понимаю, является защита приложения от вредоносных файлов, пытающихся внедрить экземпляры вредоносного класса. Таким образом, он должен вызываться при открытии файлов, но при сохранении документа в файл его вызывать не нужно. Я знаю, что ты это уже знаешь. Дело может быть в том, почему ошибка возникает, когдаsaveAs
. - person Tora   schedule 16.02.2018