【问题标题】:Using FetchedResultsController and ManagedObjectContext in multiple view controllers在多个视图控制器中使用 FetchedResultsController 和 ManagedObjectContext
【发布时间】:2011-07-19 06:27:45
【问题描述】:

我的 RootViewController 包含一个简单的表格视图。选择表中的一个条目后,将显示 DetailViewController 以及有关所选条目的更多详细信息。相关数据对象的数据通过CoreData加载和持久化。如何在 didSelectRowAtIndexPath: 方法中将 FetchedResultsController 和 ManagedObjectContext 传递给 DetailViewController? 我需要在 DetailViewController.h 中为两者定义属性吗?你能给我一个代码示例吗?

【问题讨论】:

    标签: ios core-data uiviewcontroller nsfetchedresultscontroller


    【解决方案1】:

    首先,每个获取结果控制器 (FRC) 实例都针对每个 tableview 进行配置,因此您不会将 FRC 从 tableview 控制器传递到 tableview 控制器。相反,每个 tableview 控制器都实例化并专门为其 tableview 配置一个新的 FRC。

    在表视图为主视图的主从设计中,您不会将 FRC 传递给详细视图,而只是将所选表视图行表示的单个托管对象传递给。

    Apple 建议通过“依赖注入”传递托管对象上下文 (MOC)。这很简单。在最常见的设计中,您在应用程序委托中初始化 MOC,然后为每个视图控制器提供 managedObjectContext 属性。然后,当您加载/推送视图控制器时,只需将其 managedObjectContext 属性设置为 MOC。

    例如,在主从设计中,您通常有一个导航控制器 (NAV)。要了解它是如何工作的,请使用 Xcode 中基于导航的应用程序模板创建一个测试应用程序。将其标记为使用 Core Data。你会发现应用程序委托和RootViewController 都有一个managedObjectContext 属性。

    现在在应用代理的applicationDidFinishLaunching:... 方法中添加代码,使其看起来像:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
      // Override point for customization after application launch.
      // Add the navigation controller's view to the window and display.
      RootViewController *topVC=(RootViewController *) self.navigationController.topViewController;
      topVC.managedObjectContext=self.managedObjectContext;
      self.window.rootViewController = self.navigationController;
      [self.window makeKeyAndVisible];
        return YES;
    }
    

    ...然后在RootViewController.m 添加:

    - (void)viewDidAppear:(BOOL)animated
    {
      NSLog(@"self.managedObjectContext = %@",self.managedObjectContext);
      [super viewDidAppear:animated];
    }
    

    当您运行测试应用程序时,RootViewController 对象将记录它的 managedObjectContext 属性,例如:

    2011-07-19 09:24:05.193 CDNavTemplate[3203:207] self.managedObjectContext = <NSManagedObjectContext: 0x4d318a0>
    

    ...证明RootViewController 对象具有来自应用委托的托管对象上下文。

    现在,您只需为推送到导航控制器堆栈的每个视图控制器重复该过程,逐步将相同的托管对象上下文对象传递到视图层次结构中。您可以以完全相同的方式传递任何其他类型的对象。

    Apple 推荐依赖注入,因为它使代码更加模块化,并且可以轻松地在单个应用程序中使用多个托管对象上下文。您只需向每个特定的视图控制器传递它在任何特定时间所需的特定上下文。

    【讨论】:

    • 这对我来说是非常有价值的信息,我在所有书籍和文档中都在寻找这样的解释,但找不到。非常感谢 - 你让我开心!
    • 编写文档和书籍的人完全了解 API,因此他们很难理解什么让新手感到困惑。这是训练领域的大问题。我必须一直处理它。
    • 甜蜜,奇妙的解释,先生。
    • 我不明白的是:如果我使用 Master-Detail 模板创建一个新项目并包含核心数据,AppDelegate 将设置 MasterViewController 的 managedObjectContext 属性。然而 MasterViewController 仍然使用NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext]; 在许多方法中获取上下文...
    【解决方案2】:

    简而言之,有两种选择:

    1. 这两个(FetchedResultsController 和 ManagedObjectContext)都需要位于所有视图控制器都可以访问它们的位置。例如,如果它们在 App Delegate 中(Xcode 默认放置 ManagedObjectContext),您可以通过这种方式访问​​它(这将显示警告 - 因此您需要将委托键入应用程序的应用委托类) :
    NSManagedObjectContext *context = [[[UIApplication sharedApplication] delegate] managedObjectContext];
    1. 您实际上可以在创建视图控制器时将这些值传递给它们。例如,您可以创建一个子类(例如 DataViewController 或其他东西)并在该子类上具有两个属性(用于 ManagedObjectContext 和 FetchedResultsController),这些属性将在您创建它们时设置。

    【讨论】:

    • 您不应该将获取的结果控制器从视图控制器传递到视图控制器,因为 FRC 特定于每个表视图。每个 tableview 都应该有自己的 FRC。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    相关资源
    最近更新 更多