简体   繁体   中英

How to save a dictionary to core data in Swift

What is the best method to save a dictionary using Core Data? I have a dictionary defined as

var myRecipes:[String:[Recipe]]

Where Recipe is a struct with health information about a recipe. The string would be a category like "Breakfast" or "Lunch" and the Recipe array would have breakfast or lunch recipes.

What would be the best way to add new categories and add recipes to categories in Core Data?

  • In Core Data create two entities Category and Recipe .
  • In Category declare an attribute name and a to-many non-optional relationship recipes to Recipe .
  • In Recipe declare the required attributes and an optional to-one relationship category to Category .

I recommend to create the NSManagedObject subclasses manually ( Codegen Manual/None and menu Editor > Create NSManagedObject Subclass... ). Then you are able to declare the to-many relationship as native Set<Recipe> rather than typeless NSSet .

You can serialize your Dictionary to Data and save it to core data for later use. Following are example:

struct Recipe: Codable {
    let identify: String
    let name: String
}

let myRecipes:[String:[Recipe]] = ["key_1": [Recipe(identify: "r_1", name: "r_name_1")],
                                   "key_2": [Recipe(identify: "r_2", name: "r_name_2"),
                                             Recipe(identify: "r_3", name: "r_name_3")]]
let jsonData = try! JSONEncoder().encode(myRecipes) // Save this value (type: Data) to core data.
// later when you want to construct your Dictionary back, use following code:
let result = try! JSONDecoder().decode([String: [Recipe]].self, from: jsonData) // `jsonData` here is retrieved from core data.

However why not creating 2 seperated entities ( Category and Recipe ) for them? Which I think make thing a lot clearer.

Happy coding!

You can not directly store dictionary or array to core data. You can create class or struct to achieve the same and then add the required properties. Here below i giving you the example. You need to create an attribute with Transformable type in Entity.

实体图片

Task+CoreDataProperties.swift

import Foundation
import CoreData

extension Task {
    @NSManaged var task_object: NSObject?
}

FleetInfoDetails.swift

class FleetInfoDetails: NSObject, NSCoding {
    var fleetActions = [Int: FleetActions]() // here i am using another type you use according to your use.
    required init(coder aDecoder: NSCoder) {
        fleetActions = aDecoder.decodeObject(forKey: "fleetActions") as? [Int : FleetActions] ?? [Int : FleetActions]()
    }
    func encode(with aCoder: NSCoder) {
        aCoder.encode(fleetActions, forKey: "fleetActions")
    }
    init(json: NSDictionary) {
        self.fleetActions.removeAll()
        if let value = json["fleet_actions"] as? [[String:Any]] {
            for action in value {
                let currentAction = FleetActions(json: action)
                self.fleetActions[currentAction.actionType] = currentAction
            }
        }
    }
}

FleetActions.swift

class FleetActions: NSObject, NSCoding {
    var actionType: Int = 0

    required init?(coder aDecoder: NSCoder) {
        actionType = aDecoder.decodeObject(forKey: "actionType") as? Int ?? 0
    }

    func encode(with aCoder: NSCoder) {
        aCoder.encode(actionType, forKey: "actionType")
    }
    init(json: [String:Any]) {
        if let value = json["action_type"] as? Int {
            self.actionType = value
        }
    }
}

How to save

let entityDescription = NSEntityDescription.entity(forEntityName: "Task", in: taskManagedContext) // use your managedcontext
let data = Task(entity: entityDescription!, insertInto: taskManagedContext)// managedcontext
data.task_object = NSKeyedArchiver.archivedData(withRootObject: taskDetails) as NSObject
do {
    try youManagedContext.save() // user your managedcontext
    return true
} catch {
        print(error.localizedDescription)
}

How to fetch the data You need to unarchived the object.

// logic of fetc logic which will return array of type Task object i.e [Task]
for i in (0..<tasksFromDatabase!.count) {
    var innerArray = [FleetInfoDetails]()
    let taskData = NSData(data: tasksFromDatabase?[i].value(forKey: "task_object") as! Data) as Data
    let taskDetails = NSKeyedUnarchiver.unarchiveObject(with: taskData) as! FleetInfoDetails
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM