核心数据:实现添加/编辑功能的一种聪明方式

时间:2014-11-18 10:41:01

标签: ios core-data

我创建了几个使用Core Data和大量实验的应用程序,但我从未找到实现简单的Add / Edit viewController的“完美”方法。 我只想实现一个能够管理编辑和添加功能的单个控制器,我不想创建两个不同的控制器。

目前我正在使用这种方法(让我们以经典Person NSManagedObject为例)

1)addEditViewController我添加currentPerson属性

var currentPerson:Person? 

2)当我在Add-Mode中显示控制器时,此属性为零

3)当我在Edit-Mode中显示控制器时,此属性是对要编辑的人的引用

4)当我需要保存用户操作时,我只检查currentPerson是否已设置,我理解是否需要在上下文中创建新对象或只保存我需要编辑的对象。

好的,这种方法有效,但我想采用另一种似乎对编辑操作更安全的方法。检查可怕的错误

假设此人具有Address属性,需要编辑不同的viewController。

1)按照我之前的逻辑,我可以将currentPerson属性传递给我要出席的addressViewController

addressVC.currentPerson = currentPerson
presentAddressVC()

2)现在,当用户完成编辑操作并且他/她点击“保存” addressVC调用saveContext函数。

问题出在哪里?好吧......如果用户开始编辑addEditViewController中的currentPerson,然后只返回到前一个控制器,currentPerson仍然存储用户的编辑,并且一旦保存上下文在任何其他控制器中,不真正需要的数据被存储并变得持久。

如果用户点击addEditViewController上的后退按钮,我可以执行rollback,但我真的不喜欢这种行为,看起来很糟糕。

我认为使用多个上下文或在NSManagedObjects上下文中插入nil只是在操作结束时将它们移动到主上下文但我也不确定这个选择。

我知道这是一个复杂而漫长(繁琐)的问题,但我希望你能就这个问题给我一些启示。 你怎么对待这种情况?您如何看待我的方法和我提出的方法?

1 个答案:

答案 0 :(得分:1)

在我看来,你的问题是维持与单个NSManagedObjectContext的连接,而你真正想要的是建立一个树。上下文的构造相当便宜,因此您应该根据ViewController创建上下文。

因此,当您显示addEdit控制器时,您只需使用新的上下文创建它:

NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
context.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy;
context.parentContext = //parentContext
context.undoManager = nil;

将这些新上下文视为用于编辑托管对象的暂存区。唯一要记住的是,当您调用save时,它会保存到父上下文而不是一直存储到商店。为此,您需要一个递归调用一直到父进行保存。这是一个基本的递归保存:

- (void)saveChangesToDiskForManagedObjectContext:(NSManagedObjectContext *)context {
    if (context && [context hasChanges]) {
        [context save:nil];
         NSManagedObjectContext *parentContext = context.parentContext;
         [parentContext performBlock:^{
            [self saveChangesToDiskForManagedObjectContext:parentContext];
         }];
    }
}

在应用中保留托管对象并不是很好的做法,可以在其他屏幕上删除它们。所以你应该做的就是在视图控制器视图中获取这些对象会出现方法。要么是这样,要么致电refreshObject(mergeChanges:)以使您的托管对象与另一个屏幕所做的更改同步。

我真的不喜欢在用户导航回来时调用save的想法,应该有一个保存按钮,当我按下我试图关闭屏幕时,我会期待选择"完成"如果我想保存我的更改。

不要忘记你也可以使用NSUndoManager来跟踪你所有的变化,这就是上下文有一个undoManager的原因:)