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

时间:2011-04-08 15:28:09

标签: iphone ios core-data uitabbarcontroller nsmanagedobjectcontext

我有一个带有不同视图控制器的标签栏控制器,它们都使用相同的托管对象上下文,设置如下:

- (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;

}

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

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

2 个答案:

答案 0 :(得分:2)

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

在示例代码中,您将全局托管对象上下文推送到每个控制器中。然后,每个控制器都可以使用该托管对象上下文执行某些操作。代码中不清楚的一件事是您是将其他视图控制器推送到导航堆栈还是以模态方式显示其他视图。我的假设是你是,并且任何控制器和相关视图都可以改变托管对象。

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

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

为了说明,请注意以下图表是具有多个标签的iPhone,并且每个控制器都在给定时间处理某些活动。

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

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

确定这些用例可能是困难的部分,因为我确信您了解NSManagedObjectContext的工作原理(如果不是,您应该花一些时间更彻底地了解它)。从这个简单的图表中可以看出,对于一个非常简单的用例,它引入了另一个复杂维度。所以我的观点是,如果您不希望在代码库成熟时拆掉并重新构建代码库,那么您必须提前计划。

答案 1 :(得分:1)

如果您希望将对托管对象上下文的更改自动传播到您的界面,并且您正在使用表视图(甚至自定义视图),则可以使用NSFetchedResultsController。此类监视更改的上下文并触发其委托方法,允许您仅在必要时重新加载视图。