Ios 如何使用具有正确值的Swift在CoreData中保存解码值
我们在swift中使用CoreData来存储json数据并检索它们。我们希望将json数据保存在数据库中,因此我们使用Example.json in Service.swift作为jsonData。我提供了POI模型,因为它是由XCode创建的,并且它使用可编码、解码和编码。上下文是通过依赖注入传递的,它是一个单例。该模型使用带有“NSSecureUnarchiveFromData”的Transformable作为转换器。问题是:在解码时,我可以在调试模式下看到所有属性,但当应该保存上下文时,所有值都是“nil”。如何解决这个问题?其他型号都很相似,所以我没有包括在内。如果您需要任何其他文件或其中的任何部分,请随时询问。问题并不完全清楚,但在使用不适用于可转换属性的值时,这听起来类似于一个常见问题。可转换文件必须符合Ios 如何使用具有正确值的Swift在CoreData中保存解码值,ios,swift,core-data,codable,Ios,Swift,Core Data,Codable,我们在swift中使用CoreData来存储json数据并检索它们。我们希望将json数据保存在数据库中,因此我们使用Example.json in Service.swift作为jsonData。我提供了POI模型,因为它是由XCode创建的,并且它使用可编码、解码和编码。上下文是通过依赖注入传递的,它是一个单例。该模型使用带有“NSSecureUnarchiveFromData”的Transformable作为转换器。问题是:在解码时,我可以在调试模式下看到所有属性,但当应该保存上下文时,所
NSCoding
或NSSecureCoding
的要求。Swift类型通常不会这样做,因为除非继承自NSObject
,否则无法遵守这些协议。使用Codable
不是一回事。它的用途相同,但不能与NSCoding
互操作
在这种情况下,对JSON进行解码是可行的,但是解码后的数据无法保存,因为它无法转换
如果这里的情况与此类似,您可以将属性更改为“二进制”,然后在访问它们时进行与数据的转换。或者,尝试更改为符合
NSCoding
的类型,并坚持使用transformables。听起来像是并发问题-您是否在后台线程上下载和处理该json?该json以前已下载,如果在添加属性的行中添加断点,我可以正确读取内容。这就是为什么我不知道自己是如何的。已设置,但在上下文中似乎为零。哪些属性使用可转换属性?@TomHarrington每个属性都不是基本类型,因此“title”、“properties”、“coordinates”。我使用模型中可以看到的类作为自定义类,例如坐标是一个几何体类,它本身就是一个模型。Title是一个字典,属性也是,但它使用any,因为可能包含另一个dict,但在实现CoreData之前,我们设法让一切正常工作,现在它必须使用它。
// Service.swift
let decoder = JSONDecoder()
decoder.userInfo[CodingUserInfoKey.managedObjectContext] = self.coreDataManager.managedObjectContext
do {
_ = try decoder.decode([POI].self, from: jsonData)
self.coreDataManager.saveContext()
print("Saved")
}
catch{
print(error.localizedDescription)
}
// POI+CoreDataClass.swift
@objc(POI)
public class POI: NSManagedObject, Codable {
...
required public convenience init(from decoder: Decoder) throws {
guard let context = decoder.userInfo[CodingUserInfoKey.managedObjectContext] as? NSManagedObjectContext else {
throw DecoderConfigurationError.missingManagedObjectContext
}
let entity = NSEntityDescription.entity(forEntityName: "POI", in: context)!
self.init(entity: entity, insertInto: context)
let encodedValues = try decoder.container(keyedBy: CodingKeys.self)
let idString = try encodedValues.decode(String.self, forKey: .id)
self.id = UUID.init(uuidString: idString)!
self.externalId = try encodedValues.decode(String.self, forKey: .externalId)
self.title = try encodedValues.decode([String:String].self, forKey: .title)
self.coordinates = try encodedValues.decode(Geometry.self, forKey: .coordinates)
self.author = try encodedValues.decode(String.self, forKey: .author)
self.imageUrl = try encodedValues.decode(String.self, forKey: .imageUrl)
self.type = try encodedValues.decode(String.self, forKey: .type)
let propertyValues = try encodedValues.decode([String:Any].self, forKey: .properties)
self.properties = propertyValues
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
try container.encode(externalId, forKey: .externalId)
try container.encode(title, forKey: .title)
try container.encode(coordinates, forKey: .coordinates)
try container.encode(author, forKey: .author)
try container.encode(imageUrl, forKey: .imageUrl)
try container.encode(type, forKey: .type)
try container.encode(properties, forKey: .properties)
}
private enum CodingKeys: String, CodingKey {
case id
case externalId
case title
case coordinates
case author
case imageUrl
case type
case properties
}
}
enum DecoderConfigurationError: Error {
case missingManagedObjectContext
}
// POI+CoreDataProperties.swift
extension POI {
@nonobjc public class func fetchRequest() -> NSFetchRequest<POI> {
return NSFetchRequest<POI>(entityName: "POI")
}
@NSManaged public var author: String
@NSManaged public var coordinates: Geometry
@NSManaged public var externalId: String
@NSManaged public var id: UUID
@NSManaged public var imageUrl: String
@NSManaged public var properties: [String:Any]
@NSManaged public var title: [String:String]
@NSManaged public var type: String
}
// CoreDataManager.swift
...
func saveContext() {
let context = persistentContainer.viewContext
if context.hasChanges {
do {
try context.save()
} catch {
// The context couldn't be saved.
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
// Example.json
..
{
"id": "0c0ef61d-9507-4400-8e5e-e7dc31a34370",
"externalId": "node/1234567890",
"title": {
"de": "Küche",
"en": "kitchen"
},
"coordinates": {
"type": "Point",
"values": [
{
"lat": 52.123456,
"lon": 13.123456
}
]
},
"author": "Authorname",
"imageUrl": "null",
"type": "Type",
"properties": {
"Website": {
"de": "https://website.com/de"
},
"wheelchair": false,
"start_date": 2020
}
}
..