一对多关系制定者

时间:2017-04-15 13:15:59

标签: ios swift core-data swift3 one-to-many

这是我第一次在swift中使用Core Data。我真的非常喜欢它,但这也是一个挑战,确保我的Appdelegate能够保存等等。

问题

基本上我正在创建预算应用。预算结束后,我需要获取当前预算并将其存储到历史实体中。现在我有两个不同的实体在这里工作:

NewBudgetCreateMO和HistoryBudgetHolderMO。应该发生的是,HistoryBudgetHolder应该将预算(newBudgetCreateMO)添加到它的一对多关系中。这是我的图表及其关系的图像。

The data model

现在,如果我设置正确,我应该允许在我的历史记录中添加尽可能多的NewBudgetCreateMOs添加它们吗?下面的代码是我的History实体的生成代码,它显示它包含一个NSSet

extension HistoryBudgetHolderMO {

@nonobjc public class func fetchRequest() -> NSFetchRequest<HistoryBudgetHolderMO> {
    return NSFetchRequest<HistoryBudgetHolderMO>(entityName: "HistoryBudgetHolder");
}

@NSManaged public var budgets: NSSet?

}

extension HistoryBudgetHolderMO {

@objc(addBudgetsObject:)
@NSManaged public func addToBudgets(_ value: NewBudgetCreateMO)

@objc(removeBudgetsObject:)
@NSManaged public func removeFromBudgets(_ value: NewBudgetCreateMO)

@objc(addBudgets:)
@NSManaged public func addToBudgets(_ values: NSSet)

@objc(removeBudgets:)
@NSManaged public func removeFromBudgets(_ values: NSSet)

}

所以我假设我可以使用&#34; addToBudgets&#34;添加一组数据,它似乎工作,但只有一个实例。

我正在进行添加

所以我在HistoryBudgetHolderMO上做了一个获取请求,看看我是否有数据库中的任何一个。如果没有,那么我从我的App Delegate 创建一个新的(请注意:我已经在上面的方法中完成了app delegate cast等,然后将App Delegate和Context传递给了这个方法)

private func SaveAndDeleteCurrentBudget(context : NSManagedObjectContext, appDele : AppDelegate){
    let fetchHistory : NSFetchRequest<HistoryBudgetHolderMO> = HistoryBudgetHolderMO.fetchRequest()

    //Saves the budget to the history budget. If we don't have oen we created one and add it to that
    do{
        let historyBudgets : [HistoryBudgetHolderMO] = try context.fetch(fetchHistory)
        if historyBudgets.count <= 0{
            let newHistoryBudget : HistoryBudgetHolderMO = HistoryBudgetHolderMO(context: context)
            newHistoryBudget.addToBudgets(budgetData.first!)
            print("entered new historyBudget")
        }else{
            historyBudgets.first!.addToBudgets(budgetData.first!)
        }
        appDele.saveContext()
    }catch{
        print("Error when looking for history fetch result")
    }

   //Deletes all budget data and budget entries that are currently used
    for object in budgetData{
        context.delete(object)
    }

    let fetchAllDataEntries = NSFetchRequest<NSFetchRequestResult>(entityName: "BudgetEntry")
    let deleteReq = NSBatchDeleteRequest(fetchRequest: fetchAllDataEntries)

    do{
        try context.execute(deleteReq)
    }catch{
        print("Error when deleting budget entries")
    }
    appDele.saveContext()
}
  1. 我执行获取请求并检查是否存在历史实体。如果没有,那么我创建一个新的,添加预算条目,然后保存上下文。
  2. 如果没有,那么我抓住历史记录持有者的第一个实例(因为它只有一个,因为它只是一个容器)并且我添加预算条目然后保存。
  3. 哪里变坏

    所以我第一次这样做并且它处于状态2时我得到一个值Optional(1),这意味着它存储了一个历史记录条目。然而,在此之后再添加任何内容,一直说它是可选的(1)。我试过查找无数的解决方案,尝试搞乱扩展等等。我认为这将是一个简单的Get / Set操作,但它只是不起作用。

    对此的任何帮助将不胜感激。

    感谢您花时间阅读本文。

2 个答案:

答案 0 :(得分:1)

你的解决方案现在似乎很好。我也建议摆脱HistoryBudgetHolderMO类。我可以建议在NewBudget类中添加另一个字段/属性:creationDate(Date type)。这样你总是可以获取最新的一个(例如,获取所有这些并按creationDate排序)。您可以添加一个活动/历史布尔属性,将Budgets标记为活动/非活动。另一个建议是尽量避免用力展开。而不是写

ip address

尝试使用&#39;如果让&#39;构造

budgetData.first!.attributeName 

答案 1 :(得分:0)

感兴趣的任何人的解决方案

正如我之前提到的,我仍在学习核心数据,我很感激KaraBenNensi的评论让我思考。

对,所以不需要&#34;持有人&#34;类型对象。相反,我所做的是使用了预算的最后一个索引。因此,每当我创建新预算时,我只需将它们全部保留在数组中。所以不要说:

budgetData.first!.attributeName 

我现在用

budgetData.last!.attributeName.

这意味着我的数据库将会增长,但无论如何它都会随着历史记录持有者而增长。现在,当我想显示历史记录时,我只需从budgetData核心数据模型中获取所有结果。当我想显示我的实际预算时,我只使用.last,这样我就可以获得最近创建的预算。

我希望这有助于某人,我很高兴我能弄明白。如果有人在将来需要帮助,请回复此问题,我会尽力帮助(但我不是专家!)