Swift – 核心数据播种class

我正在按照目前的教程创build一个大的类来处理种子大数据库的数据。

Using Swift to Seed a Core Data Database

我的数据库使用JSON填充,但我想要复制作者在上面的文章中使用的模式。

在文章中他提到这种做法违反了一次性使用责任。 我知道,类应该承担一个单一的责任,但是考虑到像我这样的情况,当用户login时需要种大量的数据集,还有另外一种方法吗?

我很抱歉,如果这是一个煽动性的讨论,这不是我的意图,我的问题是这种播种方式在生产中是否司空见惯,如果不是,那么实施这种数据播种的最佳模式是什么。

我不认为有可能真正回答每个人如何导入生产数据,因为每个人都可以做不同的事情。

相反,我只想提到,根据苹果的“核心数据编程指南”,导入数据的最有效方式是通过批量导入过程。 这个过程在这里详述。

https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CoreData/Articles/cdImporting.html

据说,我会将数据存储在一个JSON文件中,该文件存储在Web服务中,或作为资源存储在应用程序包中,然后使用NSJsonSerialization类将其转换为代码可以推理的基础对象。 然后,我将使用上面指南中概述的主体来创build一个批量导入过程来为您的数据库创build种子。

这几乎是,苹果的例子是非常简单的。 我还会声明最好在后台线程上运行这个进程,因为如果导入需要很长时间才能完成,OS可能会终止你的应用程序。

希望这可以帮助!

*编辑*

下面是一个如何使用协议和generics来针对任何types的对象执行任务的例子。 你可以使用这个模式来执行任何types的操作,所以只要理解并input你的核心数据逻辑。

这只是一个可以遵循的模式的例子,不应该被认为是一个即插即用的实现。 它将需要进行调整以支持核心数据批量导入和保存。 但是,它清楚地显示了一种方法来获取字典或字典数组,并将其解码为对象。 那么你对你的物体做什么完全取决于你。

protocol JSONDecodable { // This is used so you can have a unified way to instantiate an instance without relying on sub-classing NSObject init() // This can be implemented so you can manually decode a single object of the type from a dictionary static func decodeFromJSON(json: AnyObject?) -> AnyObject? // This is used so that you can manually set the values to the object. This is required as Swift reflection doesn't support dynamic property setting func setValueForKey(value: AnyObject?, forKey: String) } // This class is responsible for decoding a JSON dictionary into an object class JSONDecoder<T:JSONDecodable>: NSObject { //MARK: Initialization required override init() { // do any initialization here } //MARK: Public Methods /** Creates a single object from the JSON. This method should only be used if the JSON will only ever contain a single object :json: A dictionary of data :returns: An object of the given type */ func toSingle(json: AnyObject?) -> T? { // process single object, and return an array with the one object if let dict = json as? [NSObject: AnyObject] { return self.makeObject(dict) } return nil } /** Creates a list of objects from the JSON. This method should only be used if the JSON will contain multiple objects :json: A dictionary of data :returns: An list of objects of the given type */ func toArray(json: AnyObject?) -> [T]? { // process array if let arr = json as? [AnyObject] { return self.makeObjects(arr) } else if let dict = json as? [NSObject: AnyObject] { // process single object, and return an array with the one object var arr = [T]() arr.append(self.makeObject(dict)) return arr } return nil } //MARK: The Magic private func makeObjects(jsonArray: [AnyObject]?) -> [T]? { var returnArray: [T] = [T]() if let jArray = jsonArray { for jObject in jArray { if let dict = jObject as? [NSObject: AnyObject] { returnArray.append(self.makeObject(dict)) } } } if returnArray.count > 0 { return returnArray } else { return nil } } private func makeObject(jsonDict: [NSObject: AnyObject]) -> T { var returnObject = T.self() // this is where the init() function in the protocol comes in handy. It allows us to use generics to create a dynamic instance of our object for (key, value) in jsonDict { if let k = key as? String { returnObject.setValueForKey(value, forKey: k) // this is where the setValueForKey(value: AnyObject?, forKey: String) function in the protocol comes in handy. It allows us to let the object it's self set it's own values. } } return returnObject } } // This is an example class that implements the protocol which means it can be sent through the decoding process class Employee: NSManagedObject, JSONDecodable { //MARK: - Properties var employeID: Int! var name: Int! var hireDate: NSDate? var department: Department? //MARK: - Initialization override required init() { // Necessary to satisfy the JSONDecodable protocol } static func decodeFromJSON(json: AnyObject?) -> AnyObject? { var decoder = JSONDecoder<Employee>() return decoder.toSingle(json) } func setValueForKey(value: AnyObject?, forKey: String) { switch (forKey) { case "employeID": self.employeID = value as! Int case "name": self.name = value as! String case "hireDate": if let v = value as? String { let dateFormatter = NSDateFormatter() dateFormatter.dateFormat = "MM/dd/yyyy" self.hireDate = dateFormatter.dateFromString(v) } case "department": if let v = value as? [NSObject: AnyObject] { if let dept = Department.decodeFromJSON(dict) as? Department { self.department = dept } } default: NSLog("[setValueForKey] Unable to find property \(forKey)") } } }