了解核心数据中 NSManagedObjectContext 的使用

Posted

技术标签:

【中文标题】了解核心数据中 NSManagedObjectContext 的使用【英文标题】:Understanding use of NSManagedObjectContext in Core Data 【发布时间】:2013-03-24 10:29:02 【问题描述】:

我认为我在为 DO STUFF 创建代码方面并不差。但我在存储我的变量和持久数据方面很糟糕。我正在使用 ARC 和故事板(考虑放弃故事板,因为它们似乎在做一些我看不到的事情)。

我寻求帮助。到目前为止,我无法从我找到的资源中掌握如何做我想做的事情的概念。

我的想法是: 向用户展示了 tableviewcontroller 类型的 viewController,它向他显示每行的字符串(股票报价名称)。我认为这些字符串需要持久存储在 coredata 中。该应用程序允许用户在第二个视图控制器中添加字符串。这些也需要与第一个数据一起持久保存。然后,应用程序需要获取一些基于 Web 的数据并将它们与字符串(股票价格)一起显示。当应用程序退出时,它可以删除基于 Web 的数据并只保留字符串(股票报价名称)。

我寻求帮助。

该应用程序不显示任何警告并且编译没有任何问题。

然后它在 NSLog(@"2"); 在下面的代码中的 viewDidLoad 之后立即崩溃,* 由于未捕获的异常 'NSInvalidArgumentException' 而终止应用程序,原因:' +entityForName: nil 不是搜索实体名称“Stock”的合法 NSManagedObjectContext 参数

Appdelegate.h
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;

- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;

Appdelegate.m
@synthesize managedObjectContext = _managedObjectContext;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;

- (void)prvniSpusteni

    NSLog(@"Firt run of app, example Stocks added.");
    NSManagedObjectContext *context = [self managedObjectContext];

    // Creating, Apple, Google, Bekrshire B

    Stock *akcie1 = [NSEntityDescription insertNewObjectForEntityForName:@"Stock" inManagedObjectContext:context];
    akcie1.ticker = @"AAPL";
    akcie1.index = [NSNumber numberWithInt:0];
    Stock *akcie2 = [NSEntityDescription insertNewObjectForEntityForName:@"Stock" inManagedObjectContext:context];
    akcie2.ticker = @"HIMX";
    akcie2.index = [NSNumber numberWithInt:1];
    Stock *akcie3 = [NSEntityDescription insertNewObjectForEntityForName:@"Stock" inManagedObjectContext:context];
    akcie3.ticker = @"BRK-B";
    akcie3.index = [NSNumber numberWithInt:2];

    NSError *error;
    if (![context save:&error]) 
        NSLog(@"Error: %@", [error localizedDescription]);
    
    [self aktualizaceDatTrhu]; // method to get data from web declared in Appdelegate aswell.


ViewController.h
@property (nonatomic, strong) NSManagedObjectContext* managedObjectContext;
@property (nonatomic, strong) NSArray *ulozeneAkcie;

ViewController.m
@interface ViewController ()
@end

@implementation ViewController
@synthesize managedObjectContext;
@synthesize ulozeneAkcie;

- (void)viewDidLoad

    [super viewDidLoad];
    NSManagedObjectContext *context = managedObjectContext;
    **NSLog(@"2");**
    NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Stock" inManagedObjectContext:context];
    NSLog(@"3");
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSLog(@"4");
    [request setEntity:entityDescription];
    NSLog(@"5");
    // Nastav trideni do arraye
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]
                                        initWithKey:@"index" ascending:YES];
    [request setSortDescriptors:@[sortDescriptor]];
    NSLog(@"6");
    NSError *error;
    ulozeneAkcie = [managedObjectContext executeFetchRequest:request error:&error];
    NSLog(@"7");
    

现在我认为问题在于视图控制器以某种方式无法访问托管对象上下文。但我认为 coredata 将被视为全局数据,可以从应用程序的任何部分访问,例如一盒乐高积木。

我最深切地感谢任何阅读到这里的人,甚至更深地感谢任何提供见解的人。

如果有人愿意,我很想举一个例子,说明在哪里放置哪些属性,在哪里放置哪些合成器和钩子,以便实际工作。

P.S.:我在网上发现了一些“类似”的问题,其中提到了将 MOC 传递给 viewController,但是由于我的应用程序是用故事板制作的,所以我错过了很多钩子和插座,添加它们并不能解决任何问题..

【问题讨论】:

错误信息表明context(第二个参数)是nilNSManagedObjectContext 和其他核心数据组件不是“全局的”。通常,核心数据通过应用程序委托进行初始化/管理。建议阅读developer.apple.com/library/mac/#documentation/cocoa/Conceptual/…,并阅读raywenderlich.com/934/…等核心数据教程 【参考方案1】:

根据您的问题,您应该检查两件不同的事情。

首先,您是否正确设置了核心数据堆栈?通常,正如 Apple 所做的那样,这可以在应用程序委托中进行设置。

那么,你是否正确地注入了上下文引用?这可以像下面这样执行。

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender

    if ([[segue identifier] isEqualToString:@"segueIdentifier"])
    
        ViewController *vc = [segue destinationViewController];
        vc.managedObjectContext = mainContext; // pass here the context that you created in app delegate or you grabbed from another property, for example
    

现在,在您的viewDidLoad

[super viewDidLoad];

if(!self.managedObjectContext) // see if context is nil
    NSAssert(NO, @"The context cannot be nil"); // just for test purposes

NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Stock" inManagedObjectContext:context];
NSLog(@"3");
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSLog(@"4");
[request setEntity:entityDescription];
NSLog(@"5");
// Nastav trideni do arraye
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]
                                    initWithKey:@"index" ascending:YES];
[request setSortDescriptors:@[sortDescriptor]];
NSLog(@"6");
NSError *error;
ulozeneAkcie = [managedObjectContext executeFetchRequest:request error:&error];
NSLog(@"7");

【讨论】:

以上是关于了解核心数据中 NSManagedObjectContext 的使用的主要内容,如果未能解决你的问题,请参考以下文章

通过电子邮件发送 coreData

机器学习实践:了解数据核心的通用方法!

机器学习实践:了解数据核心的通用方法!

深入了解Zookeeper核心原理

10分钟了解Vuex的使用步骤和核心特性

了解核心数据并在删除后保存 NSManagedObjectContext