我有一个看起来像这样的模型,其中包含NSManagedObject属性,即blendsWith
属性,它是[Tag]
的一种类型:
extension Oil {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Oil> {
return NSFetchRequest<Oil>(entityName: "Oil")
}
@NSManaged public var blendsWith: [Tag]?
@NSManaged public var color: String?
@NSManaged public var commentsCount: Int64
@NSManaged public var id: Int64
@NSManaged public var imageURL: String?
@NSManaged public var latinName: String?
@NSManaged public var name: String?
@NSManaged public var properties: NSObject?
@NSManaged public var research: String?
@NSManaged public var resourceType: String?
@NSManaged public var viewsCount: Int64
}
public class Oil: NSManagedObject, Codable {
enum CodingKeys: String, CodingKey {
case resourceType = "resource_type"
case id, name
case imageURL = "image_url"
case color
case latinName = "latin_name"
case emotions
case safetyInformation = "safety_information"
case fact, research
case viewsCount = "views_count"
case commentsCount = "comments_count"
case blendsWith = "blends_with"
case foundInBlends = "found_in_blends"
case properties
case sourcingMethods = "sourcing_methods"
case usages
}
required convenience public init(from decoder: Decoder) throws {
let context = CoreDataHelper.sharedInstance.persistentContainer.viewContext
guard let entity = NSEntityDescription.entity(forEntityName: "Oil", in: context) else { fatalError() }
self.init(entity: entity, insertInto: context)
let container = try decoder.container(keyedBy: CodingKeys.self)
self.resourceType = try! container.decodeIfPresent(String.self, forKey: .resourceType)!
self.id = try! container.decodeIfPresent(Int64.self, forKey: .id)!
self.name = try! container.decodeIfPresent(String.self, forKey: .name)!
self.imageURL = try! container.decodeIfPresent(String.self, forKey: .imageURL)!
self.color = try! container.decodeIfPresent(String.self, forKey: .color)!
self.viewsCount = try! container.decodeIfPresent(Int64.self, forKey: .viewsCount)!
self.viewsCount = try! container.decodeIfPresent(Int64.self, forKey: .viewsCount)!
self.commentsCount = try! container.decodeIfPresent(Int64.self, forKey: .commentsCount)!
self.latinName = try! container.decodeIfPresent(String.self, forKey: .latinName)!
if let blendsWith = try container.decodeIfPresent([Tag].self, forKey: CodingKeys.blendsWith) {
self.blendsWith = blendsWith
}
}
public func encode(to encoder: Encoder) throws {
}
}
Tag
看起来像这样:
extension Tag {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Tag> {
return NSFetchRequest<Tag>(entityName: "Tag")
}
@NSManaged public var id: Int64
@NSManaged public var name: String?
@NSManaged public var resourceType: String?
@NSManaged public var tagType: String?
@NSManaged public var viewsCount: Int64
}
public class Tag: NSManagedObject, Codable {
enum CodingKeys: String, CodingKey {
case resourceType = "resource_type"
case id, name
case viewsCount = "views_count"
case tagType = "tag_type"
}
required convenience public init(from decoder: Decoder) throws {
let context = CoreDataHelper.sharedInstance.persistentContainer.viewContext
guard let entity = NSEntityDescription.entity(forEntityName: "Tag", in: context) else { fatalError() }
self.init(entity: entity, insertInto: context)
let container = try decoder.container(keyedBy: CodingKeys.self)
self.resourceType = try! container.decodeIfPresent(String.self, forKey: .resourceType)!
self.id = try! container.decodeIfPresent(Int64.self, forKey: .id)!
self.name = try! container.decodeIfPresent(String.self, forKey: .name)!
if let viewsCount = try container.decodeIfPresent(Int64.self, forKey: .viewsCount) {
self.viewsCount = viewsCount
} else {
self.viewsCount = 0
}
if let tagType = try container.decodeIfPresent(String.self, forKey: .tagType) {
self.tagType = tagType
} else {
self.tagType = "lol"
}
}
public func encode(to encoder: Encoder) throws {
}
}
当我去获取本地存储的Oil
数据时,发生此崩溃:
2018-08-29 20:31:30.602764+0100 EL[27994:14799374] -[EL.Tag initWithCoder:]: unrecognized selector sent to instance 0x60c000679980
2018-08-29 20:31:30.603905+0100 EL[27994:14799374] [error] error: exception handling request: <NSSQLFetchRequestContext: 0x608000181ee0> , -[EL.Tag initWithCoder:]: unrecognized selector sent to instance 0x60c000679980 with userInfo of (null)
CoreData: error: exception handling request: <NSSQLFetchRequestContext: 0x608000181ee0> , -[EL.Tag initWithCoder:]: unrecognized selector sent to instance 0x60c000679980 with userInfo of (null)
2018-08-29 20:31:30.612185+0100 EL[27994:14799374] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[EL initWithCoder:]: unrecognized selector sent to instance 0x60c000679980'
是什么原因导致此崩溃?
作为参考,我的提取方法如下:
func getItems<T : NSManagedObject>(predicate : NSPredicate? = nil) -> [T]{
do {
let reqest = T.fetchRequest()
reqest.predicate = predicate
if let items = try persistentContainer.viewContext.fetch(reqest) as? [T] {
return items
} else {
return [T]()
}
} catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
return [T]()
}
}
并且是这样的:
let arrat : [Oil] = CoreDataHelper.sharedInstance.getItems()
答案 0 :(得分:0)
如果调试此代码,它是否曾经进入Tag init
函数?看来编译器没有看到您的Tag.init函数,这很可能是由于Oil对象的数据模型未正确设置blendsWith
属性的类类型。
检查数据模型是否为Oil,并确保将blendsWith
设置为正确的代码类型。
编辑:
为了让Core Data获得您的班级设置,您可能需要在班级定义之前添加objc
标志:
@objc(Tag)
public class Tag ...
答案 1 :(得分:0)
Core Data通常将Transformable
编码为Data
(照此存储),对NSManagedObject
进行编码可能会做您不希望的事情。对其进行解码可能使事情“更多”变得出乎意料。 (由NSKeyedArchiver
和NSKeyedUnarchiver
在分配/使用时自动进行编码。)
如果您想使用Transformable
,则由于上面的论点,使其成为NSManagedObject
是没有意义的。 (我至少没有经验,也没有听说过会有什么用。)
因此,通常使用Transformable
或CoreData-relationships
(带有NSManagedObject
)来模拟CoreData中的一个关系,但不能同时使用两者来模拟单个关系。