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
相关产品推荐
相关产品推荐

