核心数据和Xcode 11:请切换到使用“NSSecureUnarchiveFromData”或NSSecureUnarchiveFromDataTransformer的子类

w46czmvw  于 2022-12-27  发布在  Hive
关注(0)|答案(7)|浏览(225)

刚刚迁移到Xcode 11,在启动时出现以下崩溃:
核心数据:故障:此应用程序中的一个或多个模型正在使用转换器名称未设置或设置为NSKeyedUnarchiveFromDataTransformerName的可转换属性。请切换为使用“NSSecureUnarchiveFromData”或NSSecureUnarchiveFromDataTransformer的子类。在某些情况下,如果指定nil,核心数据将默认使用“NSSecureUnarchiveFromData”。并且包含不支持NSSecureCoding的类的可转换属性将变得不可读。
核心数据:警告:实体“Group”的属性“color”使用的是nil或不安全的NSValueTransformer。请切换为使用“NSSecureUnarchiveFromData”或NSSecureUnarchiveFromDataTransformer的子类。
我使用下面的代码在启动时创建一个NSPersistentContainer

private let container: NSPersistentContainer = {
    let container = NSPersistentContainer(name: "MyApp", managedObjectModel: MyAppModelVersion.current.managedObjectModel())
    let storeDescription = NSPersistentStoreDescription(url: getStoreURLWithUserName())
    storeDescription.shouldMigrateStoreAutomatically = true
    storeDescription.shouldInferMappingModelAutomatically = true
    container.persistentStoreDescriptions = [storeDescription]
    return container
}()

执行此行后立即出错:

let container = NSPersistentContainer(name: "MyApp", managedObjectModel: MyAppModelVersion.current.managedObjectModel())

我还有一个属性叫做'Color in a Group'实体,它是可转换的:

@NSManaged public var color: UIColor?
@NSManaged public var hexColorValue: String?

下面是如何设置该属性:

public var hexColor: String? {
    get {
        return self.hexColorValue
    }
    set {
        self.hexColorValue = newValue
        if let str = newValue {
            self.color = UIColor(hex: str)
        }
    }
}

以下是该特性在Core Data中的外观:

我不知道如何从这次崩溃中恢复。这在Xcode 10中运行良好

3b6akqbq

3b6akqbq1#

将Transformer属性设置为NSSecureUnarchiveFromDataTransformer解决了我的警告问题。为此,请选择属性并将其转换器类型设置为NSSecureUnarchiveFromDataTransformer,然后按命令+R再次运行。
谢谢你拉特纳什瓦

pw136qt2

pw136qt22#

SWIFT 5.4.2版

这对我很有效。

    • 编辑**文章链接为here
  • 单击项目导航器中的. xcdatamodeld文件
  • 单击具有可转换属性的实体
  • 单击可转换属性
  • 单击"显示数据模型检查器"图标
  • 在"转换器"字段中输入"NSSecureUnarchiveFromDataTransformer"-编辑自Swift 5.5.2起将此设置为"NSSecureUnarchiveFromData"

您的警告/错误应该会消失。如果没有,请尝试清理您的生成文件夹并重新生成。

vltsax25

vltsax253#

这与从NSCodingNSSecureCoding协议的迁移有关,默认的ValueTransformer采用NSCoding,所以唯一对我有效的解决方案是编写我自己的采用NSSecureUnarchiveFromDataTransformer协议的Transformer
我应该说,我自己的经验来自于尝试定义一个带有Transformer类型的属性来持久化一个采用NSCoding的自定义类。我最初遇到了一个类似于OP的 errorwarning。我能够通过将属性上的Transformer字段更改为“NSSecureUnarchiveFromData”来抑制警告,正如其他人提到的那样,但我随后收到了一个错误,沿着如下:Not able to save to CoreData. SQLCore dispatchRequest Object of class “ ” not among allowed top level class list...如前所述here。将属性更改为关系的建议在我的情况下是不受欢迎的。
进一步的挖掘得出了this blog post,它详细说明了所有这一切的“原因”,并给出了一个对我有效的解决方案。该博客实际上在示例中使用了UIColor的情况,但它也适用于任何定制类。
假设你有一个CustomClass,你想把它作为一个Transformable Attribute存储在某个实体中,如果你像我一样,你可能已经采用了NSCoding并收到了前面提到的错误,解决方案是改为采用NSSecureCoding并定义一个NSSecureUnarchiveFromDataTransformer子类:

@objc(CustomClassValueTransformer)
final class CustomClassValueTransformer: NSSecureUnarchiveFromDataTransformer {

    static let name = NSValueTransformerName(rawValue: String(describing: CustomClass.self))

    // Make sure `CustomClass` is in the allowed class list,
    // AND any other classes that are encoded in `CustomClass`
    override static var allowedTopLevelClasses: [AnyClass] {
        // for example... yours may look different
        return [CustomClass.self, OtherClass.self, NSArray.self, NSValue.self]
    }

    /// Registers the transformer.
    public static func register() {
        let transformer = CustomClassValueTransformer()
        ValueTransformer.setValueTransformer(transformer, forName: name)
    }
}

然后确保将属性上的Transformer字段设置为“CustomClassValueTransformer”,将自定义类字段设置为“CustomClass”,这样就可以开始了。

pxyaymoc

pxyaymoc4#

对于Objective-C和iOS 14,以下解决方案适用于UIColor属性。

  • 首先添加NSSecureUnarchiveFromDataTransformer的新子类

@interface ColorValueTransformer : NSSecureUnarchiveFromDataTransformer

  • 将以下静态方法添加到实现文件中:
@implementation ColorValueTransformer

+ (NSArray<Class> *)allowedTopLevelClasses {
          return @[UIColor.class]; 
}

@end
  • 打开您的数据模型(例如datamodel.. xcdatamodeld)
  • 选择需要新Transformer的实体和相关属性
  • 打开数据模型检查器
  • 将类名(例如ColorValueTransformer)作为 Transformer 添加到该属性
  • 将 * 自定义类 * 更改为UIColor
  • 构建并运行...
vmdwslir

vmdwslir5#

对于可变换属性,需要在“自定义类”字段中设置其类型。
例如,我有一个存储数字数组的可转换字段,它的自定义类被声明为[Int16],这很可能是崩溃的原因,正如@vadian之前提到的,您不需要这两个字段。
修复崩溃后,可以通过将Transformer字段设置为NSSecureUnarchiveFromData(只需在字段中键入此值)来消除警告

bksxznpy

bksxznpy6#

我在更新到Xcode 11时收到了同样的警告消息,但在我的情况下,它们只是警告,而不是崩溃。
为了找到最好的解决方案,我尝试创建一个精简的示例应用,其中只有一个包含可转换属性的实体。但似乎无论我如何尝试,我都无法重现这个问题。我将模型文件从主应用复制到演示应用,当然,这失败了。
因此,我只有两个模型文件和一个简单的单元测试,它只不过是打开模型并创建一个持久存储容器:

func testDataModels() {
     openDataModel(named: "samplemodel")
     openDataModel(named: "appmodel")
 }

 func openDataModel(named name: String) {
    print("Opening \(name)")
     guard let url = findFile(forResource: name, withExtension: "momd"),
           let managedObjectModel = NSManagedObjectModel(contentsOf: url)
     else {
         XCTFail("Unable to find \(name) data model")
         return
     }
    print(url)
     _ = NSPersistentStoreCoordinator(managedObjectModel: managedObjectModel)
 }

 func findFile(forResource name: String, withExtension ext: String) -> URL? {
     if let url = Bundle(for: type(of: self)).url(forResource: name, withExtension: ext) {
         return url
     }
     return Bundle.main.url(forResource: name, withExtension: ext)
 }

appmodel导致错误消息,但示例模型不会。即使当我将appmodel剥离为单个实体时,它也会继续生成错误。
将samplemodel的内容与appmodel进行比较(在Finder中显示包内容),发现samplemodel中有一个名为.xccurrentversion的隐藏文件,而appmodel中没有。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>_XCCurrentVersionName</key>
    <string>samplemodel.xcdatamodel</string>
</dict>
</plist>

所以我为appmodel创建了一个类似的文件,并把它放在package文件夹中。令人惊讶的是,这样就消除了警告消息!相反,从samplemodel中删除.xccurrentversion文件会导致生成错误消息。这将允许隔离测试问题。
所以这可能是一个短期的修复。在此期间,我需要解决如何迁移到安全编码。

vq8itlhq

vq8itlhq7#

也许这些答案中的一些是可以接受的,在我的情况下,我去了this的职位。我希望这将是很大的帮助。

相关问题