I am pretty new in the Core Data and trying to save an array made of custom object but there is small problem: I don't know how to do it the right way. The application retrieves data from the network and writes it to the Core Data database. It contains several arrays and objects that are custom objects. There is no problem with writing strings, ints etc. But how do I save a list of custom objects? The objects used to get data from the web are a bit different to the ones used to work with Core Data, so I can't just assign them. Of course, this can be done in the next loop, but isn't there anything better? I am completely new to Core Data and I am looking for the best solutions for slightly more complex operations. Is Core Data worth using for complex operations?
CoreDataService:
protocol CoreDataServiceProtocol {
func saveCountries(countries: [Country])
func fetchCountries() -> [CountryCoreData]
}
final class CoreDataService : CoreDataServiceProtocol {
private var persistentContainer: NSPersistentContainer = {
let persistentContainer = NSPersistentContainer(name: "CountriesAPI")
persistentContainer.loadPersistentStores { _, error in
print(error?.localizedDescription ?? "")
}
return persistentContainer
}()
var viewContext: NSManagedObjectContext {
return persistentContainer.viewContext
}
func saveCountries(countries: [Country]) {
for country in countries {
let newCountry = CountryCoreData(context: viewContext)
for currency in country.currencies {
newCountry.addToCurrencyCoreData(currency)
}
//Below, I can easily create a new object that I want to assign as a parent property
var translation = TranslationCoreData(context: viewContext)
translation.br = country.translations?.br
newCountry.addToTranslationCoreData(translation)
//If there is no relationship between the models this way is pretty nice, but in my case there are several relationships
newCountry.setValue(country.alpha2Code, forKey: "alpha2Code")
newCountry.setValue(country.alpha3Code, forKey: "alpha3Code")
newCountry.setValue(country.altSpellings, forKey: "altSpellings")
newCountry.setValue(country.area, forKey: "area")
newCountry.setValue(country.borders, forKey: "borders")
newCountry.setValue(country.callingCodes, forKey: "callingCodes")
newCountry.setValue(country.capital, forKey: "capital")
newCountry.setValue(country.cioc, forKey: "cioc")
// newCountry.setValue(country.currencies, forKey: "currencies")
newCountry.setValue(country.demonym, forKey: "demonym")
newCountry.setValue(country.flag, forKey: "flag")
newCountry.setValue(country.gini, forKey: "gini")
//newCountry.setValue(country.id, forKey: "id")
// newCountry.setValue(country.languages, forKey: "languages")
newCountry.setValue(country.name, forKey: "name")
newCountry.setValue(country.nativeName, forKey: "nativeName")
newCountry.setValue(country.numericCode, forKey: "numericCode")
newCountry.setValue(country.population, forKey: "population")
newCountry.setValue(country.region, forKey: "region")
// newCountry.setValue(country.regionalBlocs, forKey: "regionalBlocs")
newCountry.setValue(country.subregion, forKey: "subregion")
newCountry.setValue(country.timezones, forKey: "timezones")
newCountry.setValue(country.topLevelDomain, forKey: "topLevelDomain")
// newCountry.setValue(country.translations, forKey: "translations")
}
do {
try viewContext.save()
print("Success")
} catch {
print("Error saving: \(error.localizedDescription)")
}
}
Model generated by CoreDataxcdatamodel - CountryCoreData:
import Foundation
import CoreData
extension CountryCoreData {
@nonobjc public class func fetchRequest() -> NSFetchRequest<CountryCoreData> {
return NSFetchRequest<CountryCoreData>(entityName: "CountryCoreData")
}
@NSManaged public var alpha2Code: String?
@NSManaged public var alpha3Code: String?
@NSManaged public var altSpellings: [String]?
@NSManaged public var area: Double
@NSManaged public var borders: [String]?
@NSManaged public var callingCodes: [String]?
@NSManaged public var capital: String?
@NSManaged public var cioc: String?
@NSManaged public var currencies: [CurrencyCoreData]?
@NSManaged public var demonym: String?
@NSManaged public var flag: String?
@NSManaged public var gini: Double
@NSManaged public var id: UUID?
@NSManaged public var languages: [LanguageCoreData]?
@NSManaged public var name: String?
@NSManaged public var nativeName: String?
@NSManaged public var numericCode: String?
@NSManaged public var population: Int16
@NSManaged public var region: String?
@NSManaged public var regionalBlocks: [RegionalBlockCoreData]?
@NSManaged public var subregion: String?
@NSManaged public var timezones: [String]?
@NSManaged public var topLevelDomain: [String]?
@NSManaged public var translations: [TranslationCoreData]?
@NSManaged public var currencyCoreData: NSSet?
@NSManaged public var languageCoreData: NSSet?
@NSManaged public var regionalBlockCoreData: NSSet?
@NSManaged public var translationCoreData: NSSet?
}
// MARK: Generated accessors for currencyCoreData
extension CountryCoreData {
@objc(addCurrencyCoreDataObject:)
@NSManaged public func addToCurrencyCoreData(_ value: CurrencyCoreData)
@objc(removeCurrencyCoreDataObject:)
@NSManaged public func removeFromCurrencyCoreData(_ value: CurrencyCoreData)
@objc(addCurrencyCoreData:)
@NSManaged public func addToCurrencyCoreData(_ values: NSSet)
@objc(removeCurrencyCoreData:)
@NSManaged public func removeFromCurrencyCoreData(_ values: NSSet)
}
// MARK: Generated accessors for languageCoreData
extension CountryCoreData {
@objc(addLanguageCoreDataObject:)
@NSManaged public func addToLanguageCoreData(_ value: LanguageCoreData)
@objc(removeLanguageCoreDataObject:)
@NSManaged public func removeFromLanguageCoreData(_ value: LanguageCoreData)
@objc(addLanguageCoreData:)
@NSManaged public func addToLanguageCoreData(_ values: NSSet)
@objc(removeLanguageCoreData:)
@NSManaged public func removeFromLanguageCoreData(_ values: NSSet)
}
// MARK: Generated accessors for regionalBlockCoreData
extension CountryCoreData {
@objc(addRegionalBlockCoreDataObject:)
@NSManaged public func addToRegionalBlockCoreData(_ value: RegionalBlockCoreData)
@objc(removeRegionalBlockCoreDataObject:)
@NSManaged public func removeFromRegionalBlockCoreData(_ value: RegionalBlockCoreData)
@objc(addRegionalBlockCoreData:)
@NSManaged public func addToRegionalBlockCoreData(_ values: NSSet)
@objc(removeRegionalBlockCoreData:)
@NSManaged public func removeFromRegionalBlockCoreData(_ values: NSSet)
}
// MARK: Generated accessors for translationCoreData
extension CountryCoreData {
@objc(addTranslationCoreDataObject:)
@NSManaged public func addToTranslationCoreData(_ value: TranslationCoreData)
@objc(removeTranslationCoreDataObject:)
@NSManaged public func removeFromTranslationCoreData(_ value: TranslationCoreData)
@objc(addTranslationCoreData:)
@NSManaged public func addToTranslationCoreData(_ values: NSSet)
@objc(removeTranslationCoreData:)
@NSManaged public func removeFromTranslationCoreData(_ values: NSSet)
}
extension CountryCoreData : Identifiable {
}