How to store JSON decodable values into Coredata using Swift

放肆的年华 提交于 2020-02-04 01:18:32

问题


I am trying to load JSON Data into CoreData. Here, I used JSON structure for decodable and after that I am trying to fetch the decodable Data into CoreData. I don’t know how to use decodable with iterate the data and fetching into coredata. Below code I tried, but not getting proper result. Please help me to resolve this.

My JSON

{
    "status": true,
    "data": [
        {
            "id": "20",
            "name": "ar1"
        },
        {
            "id": "21",
            "name": "ar2"
        },
        {
            "id": "22",
            "name": "ar3"
        }
    ]
}

My Structure For JSON

struct userList: Codable {
    let status: Bool
    let data: [userData]
}

struct userData: Codable {
    let id, name: String
}

My Coredata Entity

var users = [User]() // User is my entity name

JSON Codable and Try ing to Load Into CoreData

do {
       let result = try JSONDecoder().decode(userList.self, from:data) // here I am dong mistakes.
       let status = result.status
       if status == true {
           let newPerson = User(context: self.context)
           newPerson.id = "" // Cant able to get values
           newPerson.name = ""
           self.users.append(newPerson)

            DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
                self.tableView.reloadData()
             }
            } else {
               print(error)
             }

    } catch {
         print(error)
}

回答1:


To be able to decode JSON directly into Core Data classes you have to adopt Decodable

  • Implement two extensions to be able to pass the managed object context via the JSONDecoder

    extension CodingUserInfoKey {
        static let context = CodingUserInfoKey(rawValue: "context")!
    }
    
    extension JSONDecoder {
        convenience init(context: NSManagedObjectContext) {
            self.init()
            self.userInfo[.context] = context
        }
    }
    
  • In User adopt Decodable and add CodingKeys and the required init(from method

    public class User: NSManagedObject, Decodable {
    
        private enum CodingKeys: String, CodingKey { case name, id }
    
        public required convenience init(from decoder: Decoder) throws {
            guard let context = decoder.userInfo[.context] as? NSManagedObjectContext else { fatalError("Error: with managed object context!") }
            let entity = NSEntityDescription.entity(forEntityName: "User", in: context)!
            self.init(entity: entity, insertInto: context)
            let values = try decoder.container(keyedBy: CodingKeys.self)
            name = try values.decode(String.self, forKey: .name)
            id = try values.decode(String.self, forKey: .id)
        }
    ...
    
  • Now you need only one umbrella struct for the root object. Once again please name structs always with starting uppercase letter

    struct Root: Decodable {
        let status: Bool
        let data: [User]
    }
    
  • To decode the JSON use the custom initializer, the User instances are inserted automatically into the database

    do {
        let decoder = JSONDecoder(context: context) // context is the NSManagedObjectContext instance 
        let result = try decoder.decode(Root.self, from: data)
        if result.status {
           print("success")
           try context.save()
        }  
    catch { print(error)
    


来源:https://stackoverflow.com/questions/59629695/how-to-store-json-decodable-values-into-coredata-using-swift

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!