将 UITabBarController 与内部 UINavigationControllers 一起使用时如何共享 ManagedObjectContext

Posted

技术标签:

【中文标题】将 UITabBarController 与内部 UINavigationControllers 一起使用时如何共享 ManagedObjectContext【英文标题】:How to share a ManagedObjectContext when using UITabBarController with inner UINavigationControllers 【发布时间】:2010-11-04 18:26:06 【问题描述】:

我有一个架构问题。我的应用程序在应用程序窗口中使用 TabBarController。 ApplicationDelegate 创建 managedObjectContext,虽然它实际上并不需要它。

TabBarController 中的每个 ViewController 都是一个 NavigationViewController。每个 NavigationController 的第一个视图控制器是我的自定义视图。所有都是通过 Interface Builder 创建的链接。

现在,我如何以正确的方式传递 managedObjectContext?实际上,我需要我的视图尽快加载数据,以便当用户选择选项卡或导航到 NavigationControllers 时,数据已经存在。

所以我的问题是:

    如何正确传递上下文? 我应该在什么时候获取我的数据,即用什么方法? “viewDidLoad”还是“viewDidAppear”?

感谢所有的想法!

【问题讨论】:

【参考方案1】:

您通常应该远离从应用委托中获取共享对象。它使它的行为太像一个全局变量,并且有一大堆与之相关的问题。而且单例只是花哨的全局变量,因此除非确实必要,否则也应避免使用它们。

我会为您的每个视图控制器添加一个managedObjectContext 属性,并在您创建它们时分配它。这样一来,您的视图控制器就不会与应用代理紧密联系。

至于什么时候取数据,就懒得做。 Core Data 非常快,所以我会等到viewWillAppear: 进行获取。如果等到viewDidAppear:,则视图已经在屏幕上,数据加载时会有闪烁。但是请注意,每次您的视图可见时都会调用viewWillAppear:(例如,当用户点击导航栏上的后退按钮或模式视图控制器被关闭时),因此您可能想要跟踪您是否已经加载了数据并在后续调用中跳过加载。

【讨论】:

【参考方案2】:

我遇到了同样的问题,我会分享我的解决方案。

首先,您需要在 nib 文件的选项卡栏中引用导航控制器,确保将其连接起来。

IBOutlet UINavigationController *navigationController;

然后,按照支持文档中的建议获取 Controller 并将 managedObjectContext 发送给它:

SavedTableViewController *saved = (SavedTableViewController *)[navigationController topViewController];
saved.managedObjectContext = self.managedObjectContext;

Alex 是对的,“您通常应该远离从应用委托中获取共享对象。这使得它的行为过于像全局变量,并且与之相关的问题一团糟。”

【讨论】:

【参考方案3】:

您可以随时从应用委托中获取它,如下所示:

myApp *d = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *managedObjectContext = d.managedObjectContext;

或上述的变体。 除此之外,您可以向所有视图控制器添加一个属性并传递它,或者您可以创建一个单例并全局引用它。

【讨论】:

访问应用程序委托 managedObjectContext 是一种单例,不是吗? “managedObjectContext”是我可以随时访问的属性吗?还是我需要以某种方式投射? 示例中的指针是 NSManagedObjectContext 类型,所以不需要强制转换。【参考方案4】:

斯威夫特

您应该分享NSManagedObjectContext,但您可以分享NSPersistentStoreCoordinator

因此,您可以为每个视图创建一个新的托管对象上下文,每个视图共享同一个存储。它是首选方法,并允许并发、多线程访问。在下面的示例中,我假设您的 AppDelegate,*如果使用最新版本的 Xcode 创建并选中 Use Core Data*,具有名为 persistentStoreCoordinator 的属性:

lazy var managedObjectContext:NSManagedObjectContext? = 
    // This property is optional since there are legitimate error conditions that could cause the creation of the context to fail.

    if let appDelegate = UIApplication.sharedApplication().delegate as? AppDelegate 
        let coordinator = appDelegate.persistentStoreCoordinator
        var managedObjectContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
        managedObjectContext.persistentStoreCoordinator = coordinator
        return managedObjectContext
    
    ()

【讨论】:

以上是关于将 UITabBarController 与内部 UINavigationControllers 一起使用时如何共享 ManagedObjectContext的主要内容,如果未能解决你的问题,请参考以下文章

从UITabBarController内部呈现UINavigationController

如何防止 UITabBarController 更新子视图?

将 presentViewController 与 UITabbarController 一起使用时如何传递数据

尝试在 iOS 中将 UITabBarController 与 UITableViewController 一起使用时出现异常

将 UITabBar 放置在 UITabBarController 中的屏幕顶部

iOS:请求 UITabBarController 旋转的最新解决方案