You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NSManagedObject调用指定初始化器失败问题求助

CoreData嵌套对象获取错误求助

我正在完成以下操作:

  • 从JSON文件加载自定义对象数组
  • 将其保存到CoreData中
  • 使用NSFetchRequest获取该数据

注意:名为Cube的自定义对象数组中,每个元素包含一个名为Algorithm的自定义对象嵌套数组,Algorithm类遵循NSCoding协议(代码片段见下文)。

步骤1和2执行正常,但获取顶层实体Cube时出现错误,错误发生在嵌套类Algorithm的self.init()调用之后。


Algorithm类代码

@objc(Algorithm)
public class Algorithm: NSManagedObject, Decodable, Encodable, NSSecureCoding {

enum CodingKeys: String, CodingKey {
    case imageNumber, alg, alternativeAlgs, type, tags, isFavorite, optimalMoves, name }

public static var supportsSecureCoding = true

public func encode(with coder: NSCoder) {
    coder.encode(imageNumber, forKey: CodingKeys.imageNumber.rawValue)
    coder.encode(optimalMoves, forKey: CodingKeys.optimalMoves.rawValue)
    coder.encode(alg, forKey: CodingKeys.alg.rawValue)
    coder.encode(name, forKey: CodingKeys.name.rawValue)
    coder.encode(type, forKey: CodingKeys.type.rawValue)
    coder.encode(isFavorite, forKey: CodingKeys.isFavorite.rawValue)
    coder.encode(alternativeAlgs, forKey: CodingKeys.alternativeAlgs.rawValue)
    coder.encode(tags, forKey: CodingKeys.tags.rawValue) }

required convenience public init?(coder: NSCoder) {
    self.init()
    imageNumber = coder.decodeObject(forKey: CodingKeys.imageNumber.rawValue) as? String ?? ""
    optimalMoves = coder.decodeObject(forKey: CodingKeys.optimalMoves.rawValue) as? String ?? ""
    alg = coder.decodeObject(forKey: CodingKeys.alg.rawValue) as? String ?? ""
    name = coder.decodeObject(forKey: CodingKeys.name.rawValue) as? String ?? ""
    type = coder.decodeObject(forKey: CodingKeys.type.rawValue) as? String ?? ""
    isFavorite = coder.decodeBool(forKey: CodingKeys.isFavorite.rawValue)
    alternativeAlgs = coder.decodeObject(forKey: CodingKeys.alternativeAlgs.rawValue) as? [String] ?? []
    tags = coder.decodeObject(forKey: CodingKeys.tags.rawValue) as? [String] ?? []         }

required convenience public init(from decoder: Decoder) throws {
    guard let context = decoder.userInfo[CodingUserInfoKey.managedObjectContext] as? NSManagedObjectContext else {
        throw DecoderConfigurationError.missingManagedObjectContext
    }

    self.init(context: context)

    let container = try decoder.container(keyedBy: CodingKeys.self)
    self.imageNumber = try container.decode(String.self, forKey: .imageNumber)
    self.optimalMoves = try container.decode(String.self, forKey: .optimalMoves)
    self.alg = try container.decode(String.self, forKey: .alg)
    self.name = try container.decode(String.self, forKey: .name)
    self.type = try container.decode(String.self, forKey: .type)
    self.isFavorite = try container.decode(Bool.self, forKey: .isFavorite)
    self.alternativeAlgs = try container.decode([String].self, forKey: .alternativeAlgs) as [String]
    self.tags = try container.decode([String].self, forKey: .tags) as [String] }

public func encode(to encoder: Encoder) throws {
    var container = encoder.container(keyedBy: CodingKeys.self)
    try container.encode(imageNumber, forKey: .imageNumber)
    try container.encode(optimalMoves, forKey: .optimalMoves)
    try container.encode(alg, forKey: .alg)
    try container.encode(name, forKey: .name)
    try container.encode(type, forKey: .type)
    try container.encode(isFavorite, forKey: .isFavorite)
    try container.encode(alternativeAlgs, forKey: .alternativeAlgs)
    try container.encode(tags, forKey: .tags) }
}

extension Algorithm {

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

@NSManaged public var alg: String
@NSManaged public var alternativeAlgs: [String]
@NSManaged public var imageNumber: String
@NSManaged public var isFavorite: Bool
@NSManaged public var name: String
@NSManaged public var optimalMoves: String
@NSManaged public var tags: [String]
@NSManaged public var type: String
@NSManaged public var cube: Cube?

}

extension Algorithm : Identifiable {

}

我查资料后知道要把self.init()替换成NSManagedObject的指定初始化器,但没找到正确实现方式。替换成以下代码后应用崩溃:

let context = CoreDataManager.shared.container.viewContext
self.init(context: context)
//        self.init()

补充说明

在CoreData.xcdatamodeled文件检查器中,algorithms数组被定义为Transformable类型,并使用自定义转换器AlgorithmDataTransformer:

@objc(AlgorithmDataTransformer)
public final class AlgorithmDataTransformer: ValueTransformer {

override public func transformedValue(_ value: Any?) -> Any? {
    guard let array = value as? [Algorithm] else { return nil }
    
    do {
        return try NSKeyedArchiver.archivedData(withRootObject: array, requiringSecureCoding: true)
    } catch {
        assertionFailure("Failed to transform `Algorithm` to `Data`")
        return nil
    }
}

override public func reverseTransformedValue(_ value: Any?) -> Any? {
    guard let data = value as? NSData else { return nil }
    
    do {
        return try NSKeyedUnarchiver.unarchivedArrayOfObjects(ofClass: Algorithm.self, from: data as Data)
    } catch {
        assertionFailure("Failed to transform `Data` to `Algorithm`")
        return nil
    }
}
}

extension AlgorithmDataTransformer {
/// The name of the transformer. This is the name used to register the transformer using `ValueTransformer.setValueTrandformer(_"forName:)`. 
static let name = NSValueTransformerName(rawValue: String(describing: AlgorithmDataTransformer.self))

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

内容的提问来源于stack exchange,提问作者thatGuyNeil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 14:45:47