我正在努力理解MagicalRecord和CoreData的所有内容。所以说,我有2段代码做同样的事情,其中tallyM是在MR_defaultContext中运行的托管对象。
选项1:
Tally *tallyM = (Tally *)[Tally MR_findFirstWithPredicate:predicateM];
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
Tally *tallyMLocal = [tallyM MR_inContext:localContext];
tallyMLocal.tl_countMale = [NSString stringWithFormat:@"%ld", (long)uiTallyMaleCounter];
} completion:^(BOOL success, NSError *error) {
[self updateTallies_APICall:[tallyM MR_inContext:[NSManagedObjectContext MR_defaultContext]]];
}];
选项2:
Tally *tallyM = (Tally *)[Tally MR_findFirstWithPredicate:predicateM];
tallyM.tl_countMale = [NSString stringWithFormat:@"%ld", (long)uiTallyMaleCounter];
[tallyM.managedObjectContext MR_saveToPersistentStoreAndWait];
[self updateTallies_APICall:[tallyM MR_inContext:[NSManagedObjectContext MR_defaultContext]]];
问题:
哪一个更好?我知道当你需要异步保存时可以使用saveWithBlock,但还有其他区别吗? 选项1 是否比选项2 更安全或更好?
在选项1 中,我有一个在MR_defaultContext中运行的tallyM。然后在saveWithBlock中,我通过更改tallyMLocal和保存上下文来更改tallyM。我可以100%确定在saveWithBlock运行之后,在完成处理程序中(当我需要继续使用tallyM时),tallyM(仍然在MR_defaultContext中运行)将更新tl_countMale吗?
在选项1 中,在完成处理程序中,是否仍需要调用以下代码?我假设(已经通过控制台检查,但只是想确定)在执行saveWithBlock之后,tallyM仍在MR_defaultContext中运行。那么需要再次调用MR_inContext吗?
[tallyM MR_inContext:[NSManagedObjectContext MR_defaultContext]]
假设我根本不需要异步保存。所以我可以使用选项2 或 saveWithBlockAndWait 。 saveWithBlockAndWait 是否比选项2 更好?
我只是想确保我最终正确理解了MagicalRecords和CoreData的行为。
答案 0 :(得分:3)
就个人而言,我会避免选项2中的模式。我们的想法是,您应该使用单个托管对象上下文作为托管对象集合上的操作范围。这就是为什么大多数示例使用以下模式:
NSManagedObjectContext *localContext = //...;
NSManagedObject *localObject = [otherObject MR_inContext:localContext];
///make changes to localObject
[localContext MR_saveToPersistentStoreAndWait];
[MagicalRecord saveWithBlock:]方法基本上在更方便的API中实现了这种模式。
我还建议不要隐式使用defaultContext。在您的代码中更明确地说明这一点,因为当您的应用程序开始处理线程时,您可能需要将其交换出来。
完成处理程序的编写方式是在保存操作完成100%后始终回调它们。我建议您阅读源代码以便自己查看。