I don't think it's possible to really answer how everyone imports data in production as everyone could do different things.
Instead, I just want to mention that according to Apple's "Core Data Programming Guide" the most efficient way to import data is via a batch import process. This process is detailed here.
https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CoreData/Articles/cdImporting.html
With that said I would store your data in a JSON file that is stored either on a web service, or in the app bundle as a resource, and then use the NSJsonSerialization class to convert it to foundation objects that your code can reason with. Then I would use the principals outlined in the guide above to create a bulk import process to seed your database.
That's pretty much it, and Apple's examples are pretty straight forward. I would also state it would be best to run this process on a background thread as the OS may terminate your application if the import takes a long time to complete.
Hope this helps!
* EDIT *
Here is an example of how you can use protocols and generics to perform tasks against any type of object. You can use this pattern to perform any type of operation, so just take the concept and enter your Core Data logic.
This is merely an example of a pattern one could follow, and shouldn't be considered a plug-in-play implementation. It will need to be adapted to support the Core Data bulk import and saving. However, it does clearly show a way to take a dictionary, or array of dictionaries, and decode them to objects. Then what you do with your objects is completely up to you.
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)")
}
}
}