一对多关系 setter

One To Many Relationship setter

这是我第一次在 swift 中使用核心数据。我真的很喜欢它,但确保我的 Appdelegate 保存等也是一个挑战

问题

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

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

现在,如果我设置正确,我应该允许在我的历史记录中添加任意数量的 NewBudgetCreateMO?下面的代码是为我的历史实体生成的代码,它显示它包含一个 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)

}

所以我假设我可以只使用 "addToBudgets" 添加一组数据,它似乎确实有效,但只有一个实例。

我在哪里添加

所以我在 HistoryBudgetHolderMO 上执行了一个获取请求,以查看数据库中是否有任何内容。如果没有,那么我从我的 App Delegate 创建一个新的(请注意:我已经在上面的方法中完成了 App Delegate 转换等,然后将 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. 如果不是,那么我会获取历史记录持有者的第一个实例(因为它只是一个容器,所以应该只有一个),然后添加预算条目然后保存。

哪里变坏了

所以我第一次这样做时它处于状态 2,我得到一个 Optional(1) 的值,这意味着它已经存储了一个历史条目。然而,在此之后的任何更多添加都继续说它是可选的(1)。我已经尝试查找无数解决方案,尝试弄乱扩展等。我认为这将是一个简单的 Get/Set 操作,但它就是行不通。

如有任何帮助,我们将不胜感激。

感谢您花时间阅读本文。

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

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

对,所以不需要 "holder" 类型的对象。相反,我所做的是我使用了我预算的最后一个索引。所以每次我创建新预算时,我只是将它们全部保存在数组中。所以与其说:

budgetData.first!.attributeName 

我现在用

budgetData.last!.attributeName.

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

我希望这对某人有所帮助,我很高兴我能弄明白。如果以后有人需要帮助,请回复此消息,我会尽力提供帮助(但我不是专家!)

您的解决方案现在看来不错。我还建议摆脱 HistoryBudgetHolderMO class。我可以建议向 NewBudget class 添加另一个 field/property:一个 creationDate(日期类型)。这样你就可以随时获取最新的(例如获取所有这些并按创建日期排序)。您还可以添加 active/historic 布尔值 属性 以将预算标记为 active/inactive。另一个建议是尽量避免强制展开。而不是写

budgetData.first!.attributeName 

尝试使用 'if let' 结构

if let budget = budgetData.first {
    budget.attributeName
}