Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 核心数据中的安全编码测量类,NSValueTransformers_Ios_Swift_Core Data_Swiftui - Fatal编程技术网

Ios 核心数据中的安全编码测量类,NSValueTransformers

Ios 核心数据中的安全编码测量类,NSValueTransformers,ios,swift,core-data,swiftui,Ios,Swift,Core Data,Swiftui,我有一个应用程序,大量使用测量。它是用SwiftUI/iOS 14编写的。我将数据保存在核心数据数据库中。在我尝试实现安全编码之前,该应用程序运行良好。我制作了一个示例应用程序,除去基本的东西。它基于Xcode的默认核心数据应用程序,几乎没有改动。同样,在我尝试使用安全编码之前,我可以很好地保存度量 xddatamodel以及错误如下: 我正在为实体使用手动codegen,它如下所示: extension Item { @nonobjc public class func fetch

我有一个应用程序,大量使用测量。它是用SwiftUI/iOS 14编写的。我将数据保存在核心数据数据库中。在我尝试实现安全编码之前,该应用程序运行良好。我制作了一个示例应用程序,除去基本的东西。它基于Xcode的默认核心数据应用程序,几乎没有改动。同样,在我尝试使用安全编码之前,我可以很好地保存度量

xddatamodel
以及错误如下:

我正在为实体使用手动codegen,它如下所示:

extension Item {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Item> {
        return NSFetchRequest<Item>(entityName: "Item")
    }

    @NSManaged public var timestamp_: Date?
    @NSManaged private var notes_: String?
    @NSManaged private var length_: Measurement<UnitLength>?

    public var timestamp: Date {
        get { timestamp_ ?? Date(timeIntervalSince1970: 0) }
        set { timestamp_ = newValue }
    }

    public var notes: String {
        get { notes_ ?? "Add Notes Here..." }
        set { notes_ = newValue }
    }

    public var length: Measurement<UnitLength> {
        get { length_ ?? Measurement(value: 0, unit: UnitLength.meters) }
        set { length_ = newValue }
    }

}
@objc(UnitLengthValueTransformer)
final class UnitLengthValueTransformer: NSSecureUnarchiveFromDataTransformer {
    static let name = NSValueTransformerName(rawValue: String(describing: UnitLengthValueTransformer.self))
    override static var allowedTopLevelClasses: [AnyClass] {
        return [UnitLength.self]
    }
    
    public static func register() {
        let transformer = UnitLengthValueTransformer()
        ValueTransformer.setValueTransformer(transformer, forName: name)
    }
}
extension Item {
      public var length: Measurement<UnitLength> {
        // The getter returns an actual value, not an optional. If you want to return an optional, just use:
        // get { length_ as Measurement<UnitLength> }
        get { length_ as Measurement<UnitLength>? ?? Measurement(value: 0, unit: UnitLength.meters) }
        set { length_ = newValue as NSMeasurement }
    }

}
我的ValueTransformer如下所示:

extension Item {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Item> {
        return NSFetchRequest<Item>(entityName: "Item")
    }

    @NSManaged public var timestamp_: Date?
    @NSManaged private var notes_: String?
    @NSManaged private var length_: Measurement<UnitLength>?

    public var timestamp: Date {
        get { timestamp_ ?? Date(timeIntervalSince1970: 0) }
        set { timestamp_ = newValue }
    }

    public var notes: String {
        get { notes_ ?? "Add Notes Here..." }
        set { notes_ = newValue }
    }

    public var length: Measurement<UnitLength> {
        get { length_ ?? Measurement(value: 0, unit: UnitLength.meters) }
        set { length_ = newValue }
    }

}
@objc(UnitLengthValueTransformer)
final class UnitLengthValueTransformer: NSSecureUnarchiveFromDataTransformer {
    static let name = NSValueTransformerName(rawValue: String(describing: UnitLengthValueTransformer.self))
    override static var allowedTopLevelClasses: [AnyClass] {
        return [UnitLength.self]
    }
    
    public static func register() {
        let transformer = UnitLengthValueTransformer()
        ValueTransformer.setValueTransformer(transformer, forName: name)
    }
}
extension Item {
      public var length: Measurement<UnitLength> {
        // The getter returns an actual value, not an optional. If you want to return an optional, just use:
        // get { length_ as Measurement<UnitLength> }
        get { length_ as Measurement<UnitLength>? ?? Measurement(value: 0, unit: UnitLength.meters) }
        set { length_ = newValue as NSMeasurement }
    }

}
据我所知,存在分歧,UnitLength的类标题为:

open class UnitLength : Dimension, NSSecureCoding 
因此,它确实符合NSSecureCodeding

我使用了以下参考资料:

我仍然会遇到同样的错误:

Fatal error: Unresolved error Error Domain=NSCocoaErrorDomain Code=134060 "A Core Data error occurred.", [:]: file Core_Data_Test/ContentView.swift, line 57

我不知道我做错了什么导致了这次撞车。

多亏了@LeoDabus,我终于能够解决这个问题。关键是将Swift测量转换为NSMEASURATION,并在核心数据中使用NSMEASURATION。您需要将自定义类设置为
NSMeasurement
。您的转换器将是自定义值转换器。我打电话给我的
NSMeasurementValueTransformer
。您的.xcdatamodeld将如下所示:

extension Item {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Item> {
        return NSFetchRequest<Item>(entityName: "Item")
    }

    @NSManaged public var timestamp_: Date?
    @NSManaged private var notes_: String?
    @NSManaged private var length_: Measurement<UnitLength>?

    public var timestamp: Date {
        get { timestamp_ ?? Date(timeIntervalSince1970: 0) }
        set { timestamp_ = newValue }
    }

    public var notes: String {
        get { notes_ ?? "Add Notes Here..." }
        set { notes_ = newValue }
    }

    public var length: Measurement<UnitLength> {
        get { length_ ?? Measurement(value: 0, unit: UnitLength.meters) }
        set { length_ = newValue }
    }

}
@objc(UnitLengthValueTransformer)
final class UnitLengthValueTransformer: NSSecureUnarchiveFromDataTransformer {
    static let name = NSValueTransformerName(rawValue: String(describing: UnitLengthValueTransformer.self))
    override static var allowedTopLevelClasses: [AnyClass] {
        return [UnitLength.self]
    }
    
    public static func register() {
        let transformer = UnitLengthValueTransformer()
        ValueTransformer.setValueTransformer(transformer, forName: name)
    }
}
extension Item {
      public var length: Measurement<UnitLength> {
        // The getter returns an actual value, not an optional. If you want to return an optional, just use:
        // get { length_ as Measurement<UnitLength> }
        get { length_ as Measurement<UnitLength>? ?? Measurement(value: 0, unit: UnitLength.meters) }
        set { length_ = newValue as NSMeasurement }
    }

}
我将自定义值转换器定义为:

@objc(NSMeasurementValueTransformer)
final class NSMeasurementValueTransformer: NSSecureUnarchiveFromDataTransformer {
    static let name = NSValueTransformerName(rawValue: String(describing: NSMeasurementValueTransformer.self))
    override static var allowedTopLevelClasses: [AnyClass] {
        return [NSMeasurement.self]
    }
    
    public static func register() {
        let transformer = NSMeasurementValueTransformer()
        ValueTransformer.setValueTransformer(transformer, forName: name)
    }
}
有趣的是,我不必注册值转换器。也许有人能解释为什么,但它不需要注册就可以工作

最后,在一个扩展中,我声明了一个面向公众的变量,该变量处理从和到我想要使用的度量的变量转换,如下所示:

extension Item {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Item> {
        return NSFetchRequest<Item>(entityName: "Item")
    }

    @NSManaged public var timestamp_: Date?
    @NSManaged private var notes_: String?
    @NSManaged private var length_: Measurement<UnitLength>?

    public var timestamp: Date {
        get { timestamp_ ?? Date(timeIntervalSince1970: 0) }
        set { timestamp_ = newValue }
    }

    public var notes: String {
        get { notes_ ?? "Add Notes Here..." }
        set { notes_ = newValue }
    }

    public var length: Measurement<UnitLength> {
        get { length_ ?? Measurement(value: 0, unit: UnitLength.meters) }
        set { length_ = newValue }
    }

}
@objc(UnitLengthValueTransformer)
final class UnitLengthValueTransformer: NSSecureUnarchiveFromDataTransformer {
    static let name = NSValueTransformerName(rawValue: String(describing: UnitLengthValueTransformer.self))
    override static var allowedTopLevelClasses: [AnyClass] {
        return [UnitLength.self]
    }
    
    public static func register() {
        let transformer = UnitLengthValueTransformer()
        ValueTransformer.setValueTransformer(transformer, forName: name)
    }
}
extension Item {
      public var length: Measurement<UnitLength> {
        // The getter returns an actual value, not an optional. If you want to return an optional, just use:
        // get { length_ as Measurement<UnitLength> }
        get { length_ as Measurement<UnitLength>? ?? Measurement(value: 0, unit: UnitLength.meters) }
        set { length_ = newValue as NSMeasurement }
    }

}
扩展项{
公共变量长度:度量{
//getter返回的是实际值,而不是可选值。如果要返回可选值,只需使用:
//获取{length_uu作为度量值}
获取{length_uu作为度量值???度量值(值:0,单位:UnitLength.meters)}
将{length\=newValue设置为NSMeasurement}
}
}
您将注意到,核心数据属性的名称为
length\uu
。我仍然可以在我的应用程序中使用Swift测量,但可以将它们安全地存储在核心数据中。这修复了核心数据警告:

CoreData:此应用程序中的一个或多个模型正在使用 具有未设置的转换器名称的可转换属性, 或者从DataTransformerName设置为NSKeyedUnachiveFromDataTransformerName。请转到 使用“NSSecureUnarchiveFromData”或 NSSecureUnarchiveFromDataTransformer。在某种程度上,核心数据 当为nil时,将默认使用“NSSecureUnarchiveFromData” 指定的,以及包含不包含 支持NSSecureCodeding将变得不可读


测量结果不符合要求NSSecureCoding@LeoDabus我检查过了,测量结果符合要求。有没有想过如何将其保存为NSMeasurement?NSMeasurement有,但Measurement没有