在多个选项卡中使用相同的NSManagedObjectContext

我有一个标签栏控制器与不同的视图控制器都使用相同的pipe理对象上下文,设置如下:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { RootViewController *rootVC = [[RootViewController alloc] initWithStyle:UITableViewStyleGrouped]; rootViewController.managedObjectContext = self.managedObjectContext; UINavigationController *rootNavCon = [[UINavigationController alloc] initWithRootViewController:rootVC]; [rootVC release]; SettingsTableViewController *settingsVC = [[SettingsTableViewController alloc] initWithStyle:UITableViewStyleGrouped]; settingsVC.managedObjectContext = self.managedObjectContext; UINavigationController *settingsNavCon = [[UINavigationController alloc] initWithRootViewController:settingsVC]; [settingsVC release]; tabBarController = [[UITabBarController alloc] init]; NSArray *controllers = [NSArray arrayWithObjects:rootNavCon, settingsNavCon, nil]; tabBarController.viewControllers = controllers; [self.window addSubview:tabBarController.view]; [self.window makeKeyAndVisible]; return YES; 

}

这个想法类似于食谱示例代码,如果有另一个名为设置的选项卡提供了一个选项来pipe理类别对象。 问题是,如果您导航到用户可以select类别的视图,但是然后转到设置选项卡并删除,添加或编辑类别,则返回到“食谱”选项卡时,更改将不会立即反映出来。 因此select一个已删除的类别会引发exception。

处理这个问题的最好方法是什么? 我正在考虑设置NSNotification来在发生重要变化时提醒视图,但不确定是否有更好的方法来执行此操作,例如当视图出现时查询[managedObjectContext hasChanges]。 (如果上下文已经保存,那么这似乎不起作用。)

如果你想要更改你的托pipe对象上下文自动传播到你的接口,并使用表视图(甚至自定义视图),你可以使用NSFetchedResultsController 。 这个类监视变化的上下文并触发它的委托方法,只允许你在必要时重新加载视图。

除了“这是你必须做的devise决定”之外,你的问题真的没有答案。 仔细考虑你的用例,并做适当的事情。

在您的示例代码中,您将全局托pipe对象上下文推送到每个控制器中。 据推测,每个控制器都会使用该托pipe对象上下文进行操作。 从代码中不清楚的一件事是,您是否将其他视图控制器添加到导航堆栈或模态地显示其他视图。 我的假设是,你是,并且任何控制器和相关的视图可以改变一个pipe理对象。

在这种情况下,与标签视图控制器一起使用时,使用单个托pipe对象上下文可能不是您想要的。 标签允许用户在应用程序周围自由地漫游,以便他或她可以看到他或她想要执行的任何操作的适当视图。 允许他们从单个上下文中修改托pipe对象可能会在错误的地方显示更改,或导致失败。 听起来这是你所处的情况。

我对你的build议是为每个可能改变数据的工作stream创build多个托pipe对象上下文。 然后我猜你可以共享一个pipe理对象上下文为所有只读屏幕。 另一种select是使用专用于每个选项卡的pipe理对象上下文。 这将确保更改是孤立进行的,并在必要时传播出去,但必须注册上下文以接收更改通知,然后根据需要合并这些更改。

为了说明,下图是一个带有多个选项卡的iPhone,每个控制器在给定的时间处理一些活动。

 Tab A: Controller M |--------------- ,-------> Controller N `-------+ | via NSNotificationCenter v Tab B: Controller O |-----------------------+--------> 

控制器MO是选项卡栏控制器中viewController数组的成员。 用户在Tab A上环顾四周,然后导航到Tab B。 然后用户返回到选项卡A ,将控制器N推到选项卡A的导航堆栈上并进行一些更改(如您的类别删除示例)。 删除可能需要也可能不需要传播到Tab B.您可以通过拥有两个托pipe对象上下文来实现此目的,其中一个监听通过pipe理器广播的变更通知。

确定这些用例可能是很难的部分,因为我确定你明白NSManagedObjectContext是如何工作的(如果不是的话,你应该花一些时间来更彻底地理解它)。 从这个简单的图中可以看出,对于一个非常简单的用例,它引入了另一个复杂的维度。 所以我的观点是,如果你不想在代码基础成熟的时候拆卸和重build代码库,那么你必须事先做好计划。