通过核心数据关系改变属性值

Posted

技术标签:

【中文标题】通过核心数据关系改变属性值【英文标题】:Change Value of Attribute Through Core Data Relationship 【发布时间】:2016-02-12 05:46:02 【问题描述】:

我正在努力更新存储在与另一个实体具有“一对多”关系的实体中的值。

我的项目是一个预算应用程序。使用 NSFetchedResultsController,我可以成功地添加一个事务(填充在表中)并删除 FRC 自动保存的事务。

我有一个实体,它存储具有属性“名称”和“金额”的交易,并且我有一个单独的实体,它具有一个属性“theDate”(NSDate),它存储交易的日期。

之所以分开是因为我相信这会在组织上使其更简单——许多交易可以在同一日期发生。

在下面我创建实体并在创建新事务后存储值,然后设置关系:

 @IBAction func done(segue: UIStoryboardSegue) 
    let addTransactionVC = segue.sourceViewController as! AddTransaction
    let newTrans = addTransactionVC.newTransaction
    let date = addTransactionVC.datePicker.date

    // Create Entities
    let entity = NSEntityDescription.entityForName("DailyTransactions", inManagedObjectContext: self.managedContext)
    let relatedEntity = NSEntityDescription.entityForName("TransDates", inManagedObjectContext: self.managedContext)

    // Initialize Record
    let record = NSManagedObject(entity: entity!, insertIntoManagedObjectContext: self.managedContext)
    let recordDate = NSManagedObject(entity: relatedEntity!, insertIntoManagedObjectContext: self.managedContext)

    // Is new transaction being created or an old one being edited?
    if !addTransactionVC.isEditingTransaction 

        // Populate Record
        record.setValue(newTrans.name, forKey: "transName")
        record.setValue(newTrans.amount, forKey: "transAmount")
        recordDate.setValue(date, forKey: "theDate")

        // Create Relationship of Date to Transaction
        record.setValue(recordDate, forKey: "date")

     else 

        // If user was editing a transaction:
        let updatedObject = addTransactionVC.managedObject
        let newDate = addTransactionVC.datePicker.date

        // How do I change the date associated with this transaction?
        updatedObject.setValue(newTrans.name, forKey: "transName")
        updatedObject.setValue(newTrans.amount, forKey: "transAmount")

        // This line was meant to access the attribute in the "date" relationship:
        updatedObject.setValue(newDate, forKey: "date")

else 以上的所有内容都可以正常工作。在else 触发后,如果单元格(事务)被选中进行编辑。这一行:updatedObject.setValue(newDate, forKey: "date") 旨在简单地更新 TransDates 实体的“theDate”属性(“date”是关系的名称)。但我现在明白为什么这行不通了。

所以我在 else 语句中尝试了这个:

        let fetchRequestDates = NSFetchRequest(entityName: "TransDates")

        do 

            let dateObjects = try self.managedContext.executeFetchRequest(fetchRequestDates) as! [TransDates]
            for dateObject in dateObjects 

                // These 2 lines were to test that a date was being returned:
                let tempDate = dateObject.theDate as! NSDate
                print("dateObject is:\n\(String(tempDate))")

                if dateObject.valueForKey("theDate") as! NSDate == newDate 
                    updatedObject.setValue(dateObject, forKey: "date")
                    break
                
            

         catch let error as NSError 
            print("Could not fetch \(error), \(error.userInfo)")
        

我认为上面将简单地返回所有 TransDates 对象的数组,如果找到匹配项(b/w 数组中的内容和新的 NSDate),updatedObject 将被添加到其中,否则我会添加一些代码将 newDate 创建为新的 NSManagedObject 等。

但是在执行if dateObject.valueForKey("theDate") as! NSDate == newDate 时会发生这种情况:“致命错误:在展开可选值时意外发现 nil”。

我的两个问题:

    就我要完成的任务而言 - 更新/更改与交易相关联的日期(如果日期已经存在并包含其他交易,则此交易只是移动以加入它们),是这样吗?最好的方法是什么?

    我是否把关系的目的/功能都弄错了?

很抱歉这个冗长的问题,但我已经被困在这里好几天了。所以提前谢谢!

【问题讨论】:

【参考方案1】:

您收到此错误的原因是您试图强制解开一个 nil 值。你应该改用if let 声明:

if let date dateObject.valueForKey("theDate") as? NSDate 
    if date == newDate 
        ...
    

【讨论】:

那会是更好的做法,但在我的场景中,数组中的每个对象/每个 TransDates 对象都应该有一个“theDate”键,其中存储了一个 NSDate。 如果您收到此错误,显然不会。该值为零。每次强制解包 nil 值都会导致崩溃

以上是关于通过核心数据关系改变属性值的主要内容,如果未能解决你的问题,请参考以下文章

IOS:通过一对多关系获取核心数据

通过 2 个关系搜索核心数据

核心数据缓存 NSSet 属性

在核心数据映射模型的值表达式中使用“indexOfObject:”

NSFetchRequest GroupBy 一对多关系的属性

存储阵列属性中的核心数据或使用文件或关系实体