gpt4 book ai didi

ios - 在核心数据中检索/保存自定义对象时出错

转载 作者:行者123 更新时间:2023-12-01 21:22:06 25 4
gpt4 key购买 nike

我已经开发了一个ios应用程序,允许用户编辑乐谱表,现在我想实现数据持久性以防止更改被丢弃。
在阅读ios文档时,我注意到存在提高数据持久性的不同方法,并且我认为应用程序的最佳方法是Core Data。
考虑到我的应用程序使用了很多自定义对象,因此遇到了很多问题。
我正在尝试使用核心数据保存由两个属性组成的实体(称为评分表):

  • 名称:字符串
  • 评分:另一个自定义对象(度量)的数组,由其他自定义对象(分数元素)组成

  • 根据文档和其他问题,我决定在模型上使用Trasformable类型:
    enter image description here
    因此,我声明了一个通用类,用作score属性的变形器:
    public class NSSecureCodingValueTransformer<T: NSSecureCoding & NSObject>: ValueTransformer {
    public override class func transformedValueClass() -> AnyClass { T.self }
    public override class func allowsReverseTransformation() -> Bool { true }

    public override func transformedValue(_ value: Any?) -> Any? {
    guard let value = value as? T else { return nil }
    return try? NSKeyedArchiver.archivedData(withRootObject: value, requiringSecureCoding: true)
    }

    public override func reverseTransformedValue(_ value: Any?) -> Any? {
    guard let data = value as? NSData else { return nil }
    let result = try? NSKeyedUnarchiver.unarchivedObject(
    ofClass: T.self,
    from: data as Data
    )
    return result
    }

    /// The name of this transformer. This is the name used to register the transformer using `ValueTransformer.setValueTransformer(_:forName:)`
    public static var transformerName: NSValueTransformerName {
    let className = NSStringFromClass(T.self)
    return NSValueTransformerName("DHC\(className)ValueTransformer")
    }

    /// Registers the transformer by calling `ValueTransformer.setValueTransformer(_:forName:)`.
    public static func registerTransformer() {
    let transformer = NSSecureCodingValueTransformer<T>()
    ValueTransformer.setValueTransformer(transformer, forName: transformerName)
    }
    }
    以这种方式在DataModel文件中使用DHCMeasureValueTransformer作为trasformer。
    问题是,当我保存时,没有错误发生,但是当我为新的应用程序重新启动获取数据时,我可以仅获取计分表的名称,而计分数组为空,就像没有将任何元素放入其中一样(显然,在保存之前,我已经尝试打印数组内容,证明我正在使用非空数组)
    这是保存的代码:
    static func saveContext() {
    let context = getContext()
    do {
    try context.save()
    } catch {
    print("error during the save.")
    }
    }
    这是实体对象的两类代码:

    // DataClass
    @objc(ScoreSheet)
    public class ScoreSheet: NSManagedObject {
    static var supportsSecureCoding: Bool {
    return true
    }
    }

    //DataProperties
    extension ScoreSheet {

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

    @NSManaged public var name: String
    @NSManaged public var score: [Measure]
    }

    显然,Measure类实现了NSSecureCoding和用于解码和编码对象的方法。
    这是Measure类的实现:

    import Foundation


    class Measure: NSObject, NSCoding, NSSecureCoding {

    var elements : [ScoreElement] = []
    var timeSig : TimeSignature
    var clef : Clef
    static var supportsSecureCoding = true

    init(time : TimeSignature, clef : Clef) {
    self.timeSig = time
    self.clef = clef
    }

    func encode(with encoder: NSCoder) {
    encoder.encode(self.elements, forKey: "elements")
    encoder.encode(self.timeSig, forKey: "timeSig")
    encoder.encode(self.clef, forKey: "clef")

    }

    required convenience init? (coder decoder: NSCoder) {
    let elements = decoder.decodeObject(forKey: "elements") as! [ScoreElement]
    let timeSig = decoder.decodeObject(forKey: "timeSig") as! TimeSignature
    let clef = decoder.decodeObject(forKey: "clef") as! Clef

    self.init(time: timeSig, clef: clef)
    self.elements = elements
    }


    }

    最佳答案

    我不确定发生了什么问题,但是有一些需要修复的问题可能会影响您的结果。
    首先,计算出的变压器名称与您要使用的变压器名称不同。当此行执行并且TMeasure时,

    let className = NSStringFromClass(T.self)
    然后 className将类似于 MyProjectName.Measure。计算出的转换器名称最终类似于 NSValueTransformerName(_rawValue: DHCMyProjectName.MeasureValueTransformer),这与您在数据模型中使用的名称不匹配。所有这些都意味着您的变压器没有被使用。
    但这可能并不重要,因为如果 Measure符合 NSSecureCodingMeasure的所有属性( ScoreElementTimeSignatureClef)也符合 NSSecureCoding(由于您的代码未引发异常,所以似乎是这种情况)完全不需要自定义转换器。如果可转换的属性类型符合 NSSecureCoding,则Core Data将自动使用 NSSecureCoding。除非出于某种原因您不想或不符合 NSSecureCoding,否则您不需要自定义转换器。因此,不用变压器也没关系。
    至于 Measure为什么无法在编码/解码过程中幸存下来,我不知道,但是您可以通过消除不必要的编码/解码类的干扰来帮助清除问题。我还建议在 Measureencode(with:)方法的 init(coder:)中放置一个断点。保存和获取数据时,您应该达到这些断点。

    关于ios - 在核心数据中检索/保存自定义对象时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63727392/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com