我创建了几个使用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
只是在操作结束时将它们移动到主上下文但我也不确定这个选择。
我知道这是一个复杂而漫长(繁琐)的问题,但我希望你能就这个问题给我一些启示。 你怎么对待这种情况?您如何看待我的方法和我提出的方法?
答案 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的原因:)