使用Swift将数据分别加载到具有关系的两个Core Data实体中

时间:2019-06-06 14:41:38

标签: swift core-data relationship

在应用启动时,我正在将数据加载到两个Core Data实体中。加载普通属性没问题,但是我不知道如何在Swift 5中设置关系。

在两个相关实体中,CellData与Selector具有单一的“一对一”关系(每个Selector行可以具有许多CellData行)。

enter image description here

我的单个模型类加载了两个实体的数据...

class LoadData
{
init ()
{

使用for循环,该循环首先为选择器定义选择器实体数据...

    for count in 0...3
    {
        var text = "Value not found"
...

        switch count
        {
        case 0:
            text = "Masculine"
        case 1:
            text = "Neutral"
        case 2:
            text = "Feminine"
        case 3:
            text = "Plural"
        default:
            text = "Value unassigned"
        }

...,然后调用以下方法将数据添加到实体“选择器”。

        loadSelector(text: text, sortOrder: sortOrder, ...)
    }

...在同一init中,还有第二个for循环来定义CellData

    for count in 0...51
    {
        var text = "Cell text not found"
        var sortOrder: Int32 = 0
        ...

        sortOrder = Int32(count)
        ...
        switch count
        {
        case 0:
            text = "Blank"
            color1 = subject
            colorRangeLoc1 = 0
            colorRangeLen1 = Int32(text.count)
        ...   
        case 8:
            text = "Der Mann"
            color1 = article
            ...

        case 9:
            text = "Die Frau"
            color1 = article
            color2 = subject
            colorRangeLoc1 = 0
            colorRangeLoc2 = 4
            colorRangeLen1 = 3
            colorRangeLen2 = 4
            underlineRangeLoc1 = 1
            underlineRangeLen1 = 2
        ...

...还将每个循环中的数据传递到加载方法中。

           loadCellData(text: text, ...)
    }
}

func loadSelector(text: String, sortOrder: Int32, color1: String?, color2: String?, color3: String?, colorRangeLoc1: Int32?, colorRangeLen1: Int32?, colorRangeLoc2: Int32?, colorRangeLen2: Int32?, colorRangeLoc3: Int32?, colorRangeLen3: Int32?)
{
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    let context = appDelegate.persistentContainer.viewContext

    let entry: Selector = NSEntityDescription.insertNewObject(forEntityName: "Selector", into: context) as! Selector

    entry.text = text
    entry.sortOrder = sortOrder

    do { try context.save() }
    catch let error as NSError
    { print("Could not save. \(error), \(error.userInfo)") }
}

这可能不是最好的方法,但是我正在努力通过plist加载数据。

我不知道的是如何在CellData中创建关系。例如,情况8需要与Selector数据相关联,其中.text ='Masculine',而案例9的CellData应该与Selector条目.text ='Feminine'相关。

我是否应该在第二个for循环之前或之内重新获取Selector条目,然后在每种情况下分配?我已经尝试过了,但是没有成功-如果可能的话,请显示代码以及代码的位置。大多数信息似乎都在Obj-c中。 Swift 5太棒了!

2 个答案:

答案 0 :(得分:0)

与普通对象一样对待它们,Core Data为您处理了很多魔术。

我会创建一个方法,该方法创建所有选择器,并将它们作为字典返回,名称作为键(或其他适合您的其他集合)

func createSelectors(text: String) -> [String: Select] {
    var result = [String: Selector]() 
    //loop creating Selector 
    result[text: entity]
    return result
}

您甚至可以跳过loadSelector方法,并以

的形式进行实际实例化
let entity = Selector(context: context)
可以在createSelectors方法和try context.save()中的

最后完成操作,而不是对每个对象都完成。请注意,添加这样创建的对象会将其放入NSManagedObjectContext中,这现在足以使用这些对象,实际上可以在加载结束时进行一次保存。

现在,在创建CellData时,您可以做类似的事情

let selectors = createSelectors()
...
let cellData = CellData(context: context)
if let sel = selectors {
    cellData.selectorToData = sel
}
....

创建所有CellData实体后,您可以调用try context.save()

上面所有代码中的

context是您通过这种方式获得的托管对象,`let context = appDelegate.persistentContainer.viewContext,但您可能已经知道了。

“选择器”在Swift中是一个特殊的名称,因为它是内置的结构,因此我会认真考虑更改此实体的名称。

答案 1 :(得分:0)

我发现定义与现有记录的关系的唯一方法是从CoreData单独获取记录。

来自Hacking Swift Project 38,其中“ commit”是实例化的CoreData实体,与Author实体有关系:

var commitAuthor: Author!       // instantiate an Author object

let authorRequest = Author.createFetchRequest()     // create a fetch request...
authorRequest.predicate = NSPredicate(format: "name == %@", json["commit"]["committer"]["name"].stringValue)       // predicating the author's name...

let authors = container.viewContext.fetch(authorRequest)

commitAuthor = authors[0] }   // pull the author out of the array
// and assign the author to the commit.author relationship
commit.author = commitAuthor

尽管问题更多是关于分配关系,但以下内容(基于Joachim的回答)是一种更好的方式,以可见的方式加载数据,并可以将其传输到plist或JSON上传。基本上,要遍历字典数组:

let genders: NSArray = [["text": "Masculine", "sortOrder" : Int32(0)], ["text": "Neutral", "sortOrder" : Int32(1)], ["text": "Feminine", "sortOrder" : Int32(2)], ["text": "Plural", "sortOrder" : Int32(3)]]

    // loading a gender entity in context with a dictionary of items from array
    for eachDicItem in genders
    {
        let gender = NSEntityDescription.entity(forEntityName: "Gender",
                                                in: context)!
        let genderInContext = Gender(entity: gender,
                            insertInto: context)

        let genderDictionary = eachDicItem as! [String : Any]

        genderInContext.text = genderDictionary["text"] as? String
        genderInContext.sortOrder = genderDictionary["sortOrder"] as? Int32 ?? 99
    }

    // save the context
    do { try context.save() }
    catch let error as NSError
    { print("Could not save. \(error), \(error.userInfo)") }