[英]Core data -[Decodable.Address initWithCoder:]: unrecognised selector sent to instance
I have implemented JSON parsing with swift Codable and storing it with Coredata . 我已经用swift Codable实现了JSON解析并将其存储在Coredata中 。 My Code works fine while storing the JSON and fetching entities which don't have "transformable" attribute.
我的代码在存储不具有“ transformable”属性的JSON和获取实体时工作正常。 But fetch entity fails and crashes with below log in case where any of it attribute is transformable.
但是,如果任何实体的属性都是可转换的,则获取实体会失败并在以下日志中崩溃。 I need to keep transformable attribute in case of Custom Objects.
在自定义对象的情况下,我需要保留可变形的属性。 Have a look at below core data model classes and fetch request for my implementation.
看看下面的核心数据模型类和对我的实现的获取请求。 Console log:
控制台日志:
-[Decodable.Address initWithCoder:]: unrecognized selector sent to
instance 0x600000464c40
2018-06-14 11:26:52.768499+0530 Decodable[7870:2988621] [error] error:
exception handling request: <NSSQLFetchRequestContext: 0x600000381fb0>
, -[Decodable.Address initWithCoder:]: unrecognized selector sent to
instance 0x600000464c40 with userInfo of (null)
CoreData: error: exception handling request:
<NSSQLFetchRequestContext: 0x600000381fb0> , -[Decodable.Address
initWithCoder:]: unrecognized selector sent to instance 0x600000464c40
with userInfo of (null)
2018-06-14 11:26:52.777634+0530 Decodable[7870:2988621] ***
Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[Decodable.Address
initWithCoder:]: unrecognized selector sent to instance
0x600000464c40'
ViewController.swift ViewController.swift
let request = NSFetchRequest<Clinic>(entityName: "Clinic")
request.returnsObjectsAsFaults = true
do
{
managedObjectContext = appDelegate.persistentContainer.viewContext
let result = try managedObjectContext.fetch(request)//***Crashes!!
}
catch
{
print("no record found")
}
Clinic+CoreDataClass.swift Clinic + CoreDataClass.swift
import Foundation
import CoreData
public class Clinic: NSManagedObject, NSCoding {
public func encode(with aCoder: NSCoder) {
aCoder.encode(address, forKey: ClinicCodingKeys.address.rawValue)
// also encode other class attributes
}
public required convenience init?(coder aDecoder: NSCoder) {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
guard let contextUserInfoKey = CodingUserInfoKey.context,
let managedObjectContext =
appDelegate.persistentContainer.viewContext as?
NSManagedObjectContext,
let entityDescription =
NSEntityDescription.entity(forEntityName:"Clinic", in:
managedObjectContext) else { fatalError() }
self.init(entity: entityDescription, insertInto:
appDelegate.persistentContainer.viewContext)
self.address = aDecoder.decodeObject(forKey:
ClinicCodingKeys.address.rawValue) as? Address
//*** Also decode other attributes
}
public override func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: ClinicCodingKeys.self)
try container.encode(remoteid , forKey: .remoteid)
try container.encode(landline ?? "" , forKey: .landline)
try container.encode(name ?? "", forKey: .name)
try container.encode(address , forKey: .address)
try container.encode(mobile ?? "", forKey: .mobile)
try container.encode(email ?? "", forKey: .email)
}
public required convenience init(from decoder: Decoder) throws {
guard let contextUserInfoKey = CodingUserInfoKey.context,
let managedObjectContext =
decoder.userInfo[contextUserInfoKey] as? NSManagedObjectContext,
let entity =
NSEntityDescription.entity(forEntityName:"Clinic", in:
managedObjectContext) else { fatalError() }
self.init(entity: entity, insertInto: managedObjectContext)
let values = try decoder.container(keyedBy: ClinicCodingKeys.self)
remoteid = try values.decode(Int16.self, forKey: .remoteid)
landline = try values.decode(String.self, forKey: .landline)
name = try values.decode(String.self, forKey: .name)
address = try values.decode(Address.self, forKey: .address)
mobile = try values.decode(String.self, forKey: .mobile)
email = try values.decode(String.self, forKey: .email)
}
}
Clinic+CoreDataProperties.swift Clinic + CoreDataProperties.swift
import Foundation
import CoreData
extension Clinic: Codable {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Clinic> {
return NSFetchRequest<Clinic>(entityName: "Clinic")
}
@NSManaged public var remoteid: Int16
@NSManaged public var landline: String?
@NSManaged public var name: String?
@NSManaged public var address: Address?//***** Transformable attribute
//for core data model class Address
@NSManaged public var mobile: String?
@NSManaged public var email: String?
enum ClinicCodingKeys: String, CodingKey {
case remoteid = "_id"
case landline
case name
case address
case mobile
case email
}
}
Address+CoreDataClass.swift 地址+ CoreDataClass.swift
import Foundation
import CoreData
public class Address: NSManagedObject {
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(address ?? "" , forKey: .address)
try container.encode(area ?? "" , forKey: .area)
try container.encode(postalcode ?? "" , forKey: .postalcode)
try container.encode(city ?? "" , forKey: .city)
try container.encode(state ?? "" , forKey: .state)
try container.encode(country ?? "" , forKey: .country)
try container.encode(lat ?? "" , forKey: .lat)
try container.encode(lng ?? "" , forKey: .lng)
}
public required convenience init(from decoder: Decoder) throws {
guard let contextUserInfoKey = CodingUserInfoKey.context,
let managedObjectContext =
decoder.userInfo[contextUserInfoKey] as? NSManagedObjectContext,
let entity =
NSEntityDescription.entity(forEntityName:"Address", in:
managedObjectContext) else { fatalError() }
self.init(entity: entity, insertInto: managedObjectContext)
let values = try decoder.container(keyedBy: CodingKeys.self)
address = try values.decode(String.self, forKey: .address)
area = try values.decode(String.self, forKey: .area)
postalcode = try values.decode(String.self, forKey: .postalcode)
city = try values.decode(String.self, forKey: .city)
state = try values.decode(String.self, forKey: .state)
country = try values.decode(String.self, forKey: .country)
lat = try values.decode(String.self, forKey: .lat)
lng = try values.decode(String.self, forKey: .lng)
}
}
Address+CoreDataProperties.swift 地址+ CoreDataProperties.swift
import Foundation
import CoreData
extension Address : Codable{
@nonobjc public class func fetchRequest() -> NSFetchRequest<Address> {
return NSFetchRequest<Address>(entityName: "Address")
}
@NSManaged public var address: String?
@NSManaged public var area: String?
@NSManaged public var postalcode: String?
@NSManaged public var city: String?
@NSManaged public var state: String?
@NSManaged public var country: String?
@NSManaged public var lat: String?
@NSManaged public var lng: String?
enum CodingKeys: String, CodingKey
{
case address
case area
case postalcode = "postal_code"
case city
case state
case country
case lat
case lng
}
}
I have tried implementing initWithCoder: in Clinic+CoreDataClass.swift but it gives error - Cannot invoke initWith(entity: insertInto:). 我已经尝试在Clinic + CoreDataClass.swift中实现initWithCoder :,但它给出了错误-无法调用initWith(entity:insertInto :)。 And I need to implement initwith(entity: insertinto:)
而且我需要实现initwith(entity:insertinto :)
You are fetching it wrongly NSFetchRequest<Clinic>(entityName: "Clinic")
and you are not checking entity records before saving into result variable. 您错误地获取了它
NSFetchRequest<Clinic>(entityName: "Clinic")
并且在保存到结果变量之前没有检查实体记录。
let request = NSFetchRequest<Clinic>(entityName: "Clinic")
request.returnsObjectsAsFaults = true
do
{
managedObjectContext = appDelegate.persistentContainer.viewContext
let result = try managedObjectContext.fetch(request)//***Crashes!!
}
catch
{
print("no record found")
}
Replace your code with fetchData()
function and make sure Entity name is same. 用
fetchData()
函数替换您的代码,并确保实体名称相同。
func fetchData() {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Clinic")
do{
let records = try context.fetch(fetchRequest)
if let records = records as? [NSManagedObject]{
if !records.isEmpty{
var result:[NSManagedObject] = records
print("coreData result : \(records)")
}else{
print("No record in Clinic entity")
}
}
}catch{
print("Error")
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.