简体   繁体   English

iOS9 Xcode 7-核心数据-避免对象重复

[英]iOS9 Xcode 7 - Core Data - avoiding duplicated objects

As described in WWDC2015 presentation video , in the new Xcode7 we can set the objects uniqueness directly in the Xcode model editor. 如WWDC2015 演示视频中所述,在新的Xcode7中,我们可以直接在Xcode模型编辑器中设置对象唯一性。 I was trying to implement this my code, but something is not working as expected. 我正在尝试将其实现为我的代码,但是某些功能无法正常工作。 When I try to save duplicated object, the Xcode rejects the save, but the table updates with duplicated cell. 当我尝试保存重复的对象时,Xcode拒绝保存,但是表将使用重复的单元格进行更新。

So I have set the unique attributes startdate and enddate. 因此,我设置了唯一属性startdate和enddate。

在此处输入图片说明

Then I have modified my save function to handle the error and inform the user by UIAlertController. 然后,我修改了保存功能以处理错误并通过UIAlertController通知用户。

func addContract() {
    do {
        let appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
        let context: NSManagedObjectContext = appDelegate.managedObjectContext

        let entity = NSEntityDescription.entityForName("Contract", inManagedObjectContext: context)
        let newContractData = Contract(entity: entity!, insertIntoManagedObjectContext: context)

        newContractData.startdate = dateFormatter.dateFromString(startDateTextField.text!)!
        newContractData.enddate = dateFormatter.dateFromString(endDateTextField.text!)!
        newContractData.ship = shipNameTextField.text!
        newContractData.position = positionOnBoardTextField.text!
        newContractData.workingdays = Int(workingDaysLabel.text!)!

        try context.save()
    } catch {
        let alertController = UIAlertController(
            title: "Error",
            message: "The contract exsist",
            preferredStyle: UIAlertControllerStyle.Alert)
        let okAction = UIAlertAction(
            title: "OK",
            style: UIAlertActionStyle.Cancel,
            handler: nil)
        alertController.addAction(okAction)
        presentViewController(alertController, animated: true, completion: nil)
    }
}

So far so good, but when I go back to the root controller with the cancel button, the table appears updated with duplicate cell. 到目前为止一切顺利,但是当我使用“取消”按钮返回到根控制器时,该表将显示为具有重复单元格的更新。

@IBAction func cancelButtonPressed(sender: UIBarButtonItem) {
    self.navigationController?.popToRootViewControllerAnimated(true)
}

In addition, stop and run the application removes the duplicates. 此外,停止并运行该应用程序将删除重复项。

Here it is a video of the problematic behaviour. 这是有问题的行为的视频

The generated error is as follow: 产生的错误如下:

Error Domain=NSCocoaErrorDomain Code=1551 "The operation couldn’t be completed. (Cocoa error 1551.)" UserInfo=0x7fc02d462190 {Conflicts=(
        {
        constraint =         (
            startdate,
            enddate
        );
        entity = Contract;
        objects =         (
            "<Contract: 0x7fc02d45ba60> (entity: Contract; id: 0x7fc02d019430 <x-coredata:///Contract/t0897571B-200B-4F04-AF87-D50831E2DE672> ; data: {\n    enddate = \"2017-06-13 21:00:00 +0000\";\n    position = test;\n    ship = test;\n    startdate = \"2016-06-13 21:00:00 +0000\";\n    workingdays = 366;\n})",
            "<Contract: 0x7fc02b7433c0> (entity: Contract; id: 0xd000000000100000 <x-coredata://C3318932-BEDB-4AB6-A856-103F542BCF44/Contract/p4> ; data: {\n    enddate = \"2017-06-13 21:00:00 +0000\";\n    position = test;\n    ship = test;\n    startdate = \"2016-06-13 21:00:00 +0000\";\n    workingdays = 366;\n})"
        );
    }
)}
2015-06-14 19:54:15.880 WorkingDays[6028:2219449] popToViewController:transition: called on <UINavigationController 0x7fc02c007e00> while an existing transition or presentation is occurring; the navigation stack will not be updated.

The modification of addContract() to fix the problem is as follow: 为了解决该问题,对addContract()的修改如下:

func addContract() {
    let appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
    let context: NSManagedObjectContext = appDelegate.managedObjectContext

    let entity = NSEntityDescription.entityForName("Contract", inManagedObjectContext: context)
    let newContractData = Contract(entity: entity!, insertIntoManagedObjectContext: context)
    do {
        newContractData.startdate = dateFormatter.dateFromString(startDateTextField.text!)!
        newContractData.enddate = dateFormatter.dateFromString(endDateTextField.text!)!
        newContractData.ship = shipNameTextField.text!
        newContractData.position = positionOnBoardTextField.text!
        newContractData.workingdays = Int(workingDaysLabel.text!)!

        try context.save()

    } catch {
        let alertController = UIAlertController(
            title: "Error",
            message: "The contract exsist",
            preferredStyle: UIAlertControllerStyle.Alert)
        let okAction = UIAlertAction(
            title: "OK",
            style: UIAlertActionStyle.Cancel,
            handler: nil)
        alertController.addAction(okAction)
        presentViewController(alertController, animated: true, completion: nil)

        context.deleteObject(newContractData)
        print(error)

    }
}

Are you using a NSFetchedResultsController to show the data? 您是否正在使用NSFetchedResultsController来显示数据?

It seems that the uniqueness is ensured only when you save. 似乎只有在保存时才能确保唯一性。 But Core Data still allows you to insert the object into the NSManagedObjectContext when you do: 但是,在执行以下操作时,Core Data仍然允许您将对象插入NSManagedObjectContext

let newContractData = Contract(entity: entity!, insertIntoManagedObjectContext: context)

When you save, the save operations fails, but the object is still in the context, so the NSFetchedResultsController still displays it. 保存时,保存操作失败,但是对象仍在上下文中,因此NSFetchedResultsController仍显示该对象。

Try to remove the object from the context in your catch code: 尝试从捕获代码的上下文中删除对象:

context.deleteObject(newContractData)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM