如何在核心数据中保存自定义对象列表?

How to save a custom list of objects in Core Data?

我是 Core Data 的新手,正在尝试保存由自定义对象组成的数组,但有一个小问题:我不知道如何以正确的方式做到这一点。应用程序从网络中检索数据并将其写入 Core Data 数据库。它包含几个数组和对象,它们是自定义对象。写字符串,整数等没有问题。但是如何保存自定义对象列表?用于从 Web 获取数据的对象与用于处理 Core Data 的对象有点不同,所以我不能只分配它们。当然,这可以在下一个循环中完成,但是没有更好的办法吗? 我是 Core Data 的新手,我正在寻找稍微复杂一些的操作的最佳解决方案。 Core Data 值得用于复杂操作吗?

核心数据服务:

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)")
    }
}

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 {

}

我觉得先改这些东西

而不是这个

newCountry.setValue(country.alpha2Code, forKey: "alpha2Code")

添加这一行

newCountry.alpha2Code = country.alpha2Code

在您的“保存国家/地区”功能中这样做

 func saveCountries(countries: [Country]) {
       for country in countries {
            let newCountry = CountryCoreData(context: viewContext)
            newCountry.alpha2Code = country.alpha2Code//add this line         
        }
        saveContext()
    }

创建 ViewContext 函数以便您可以重复使用它!

func saveContext(){
 do {
        try viewContext.save()
        print("Success")
    } catch {
        print("Error saving: \(error.localizedDescription)")
    }
}

使用 Transformable 类型,您可以直接在 CoreData 中保存数组,而无需 for 循环