在 iOS 中传递上下文以将 Core Data 与 Storyboard 一起使用

Posted

技术标签:

【中文标题】在 iOS 中传递上下文以将 Core Data 与 Storyboard 一起使用【英文标题】:Passing context in iOS to use Core Data with Storyboard 【发布时间】:2011-11-25 23:34:09 【问题描述】:

我在将上下文从应用委托传递到视图控制器时遇到了一些问题。 我在网上找到了很多教程,都建议使用didFinishLaunchingWithOptions 方法来创建视图控制器,设置上下文属性并推送它。 我的问题是我想使用情节提要,并且视图控制器是在其中创建和推送的,而不是在应用程序委托中。

我已尝试在我的应用委托中执行此操作:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

//instantiate local context
NSManagedObjectContext *context = [self managedObjectContext];
if (!context)

    // Handle the error.
    NSLog(@"Error: Context is null");


//reference the view controller
helloCoreDataViewController1_001 *rootViewController = [helloCoreDataViewController1_001 alloc];

// Pass the managed object context to the view controller
rootViewController.managedObjectContext = context;

return YES;

这在我的视图控制器中:

@implementation helloCoreDataViewController1_001

@synthesize name, address, phone, status, managedObjectContext;
//....

- (IBAction)saveContact

NSLog(@"name: %@",self.name.text);
NSLog(@"address: %@",self.address.text);
NSLog(@"phone: %@",self.phone.text); 

//Save the new instance of the contact entity
Contact *contact = (Contact *)[NSEntityDescription insertNewObjectForEntityForName:@"Contacts" inManagedObjectContext:managedObjectContext];

[contact setContactName:[NSString stringWithFormat:@"%@",self.name.text]];
[contact setValue:self.address.text forKey:@"address"];
[contact setContactPhone:[NSString stringWithFormat:@"%@",self.phone.text]];

NSError *error = nil;

if (![managedObjectContext save:&error])

    // Handle the error.
    NSLog(@"error: %@", error.description);
    self.status.text = @"Error: contact NOT saved";

else
    self.status.text = @"Contact saved";

当我调试时,我可以看到在应用程序委托中,上下文已正确填充,并且视图控制器中的属性也正常。 但是当我的saveContact 方法被调用时,上下文是空的。

您对此有什么建议吗?如何使用情节提要将上下文传递给视图控制器?

【问题讨论】:

【参考方案1】:

您可以通过访问在 didFinishLaunchingWithOptions 中获取 Storyboard 的 rootviewcontroller

self.window.rootViewController

而不是分配一个新的。

所以 didFinishLaunchingWithOptions 中的这两行应该如下所示:

helloCoreDataViewController1_001 *rootViewController = (helloCoreDataViewController1_001 *)self.window.rootViewController;
rootViewController.managedObjectContext = context;

【讨论】:

【参考方案2】:

与其将托管对象上下文传递给视图控制器,不如尝试从 appDelegate 在视图控制器上获取它:

- (NSFetchedResultsController *)fetchedResultsController

    if (fetchedResultsController != nil) 
        return fetchedResultsController;
    
if (managedObjectContext == nil) 
    id appDelegate = (id)[[UIApplication sharedApplication] delegate]; 
    self.managedObjectContext = [appDelegate managedObjectContext];
    ... //finish your fetch request of course...

对我来说效果很好

【讨论】:

这使你的类层次结构非常僵化,你的视图控制器现在必须知道应用程序委托并依赖它。我个人更喜欢在我的视图控制器上拥有一个我在创建视图时分配的属性。 @Chris 你是对的。这只是另一种方法。我想在我的一个具有不同上下文的应用程序中使用它。这只是另一种选择......

以上是关于在 iOS 中传递上下文以将 Core Data 与 Storyboard 一起使用的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Core Data 上下文对象必须通过环境变量传递?

Core Data 将 objectID 传递给另一个线程

iOS、Core Data 和 iCloud - 切换上下文

上下文模式?为啥 Core Data 需要它?

iOS Core Data 保存上下文错误

iOS:Core Data Merge 策略如何影响 NSManagedObjectContext 保存和刷新操作