【问题标题】:CoreData: nil is not a legal NSManagedObjectContext parameterCoreData:nil 不是合法的 NSManagedObjectContext 参数
【发布时间】:2013-01-19 10:43:20
【问题描述】:

我对 Core Data 非常陌生,并且一直在尝试学习许多教程,但其中大多数都将所有 Core Data 方法放入 AppDelegate。我读过最好远离 AppDelegate 并使用自定义数据模型类来管理这些方法。

我创建了一个自定义类来管理名为MyDataModel 的所有数据。我实现了样板核心数据代码。在我的一个视图控制器中,我有一个使用 Core Data 实现一些数据的简单方法:

- (void)getProfile {
/*
 * getProfile
 */
    NSLog(@"%@", _Model.managedObjectContext);
    Users *user = (Users *)[NSEntityDescription insertNewObjectForEntityForName:@"Users" inManagedObjectContext:_Model.managedObjectContext];

    // Set Data
    [user setValue:@"John" forKey:@"fname"];
    [user setValue:@"Smith" forKey:@"lname"];
    NSError *error;
    [_Model.managedObjectContext save:&error];
}

头文件中的代码:

#import <UIKit/UIKit.h>
#import "Users.h"
#import <CoreData/CoreData.h>
#import "DataModel.h"

@interface ProfileViewController : UIViewController

// CoreData Related
@property (strong, nonatomic) DataModel *Model;

// Instance Methods
- (void)updateProfileData;

// Core Data Method
- (void)getProfile;

@end

此方法在视图控制器的viewDidLoad 方法中调用。当我运行它时,我收到以下错误:

'+entityForName: nil is not a legal NSManagedObjectContext parameter searching for entity name 'Users''

我在 StackOverflow 上发现了一个类似的问题,可能会有所帮助,但我仍然不明白解决方案实际上是什么。

'+entityForName: nil is not a legal NSManagedObjectContext parameter - Core Data

该线程中声明的解决方案是将上下文传递给 ViewController。这是如何实现的?我已经认为我正在这样做。

编辑:DataModel.h

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#import "Workouts.h"
#import "sqlite3.h"

@interface DataModel : NSObject {
    sqlite3 *Database;
}

@property (nonatomic, strong) Workouts *currentWorkout;

// Core Data Properties
@property (nonatomic, strong) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, strong) NSManagedObjectModel *managedObjectModel;
@property (nonatomic, strong) NSPersistentStoreCoordinator *storeCoordinator;

+ (DataModel *)sharedInstance;
- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;

@end

DataModel.m:

#import "DataModel.h"

@implementation DataModel

#pragma mark - Core Data

+ (DataModel *)sharedInstance {
   static DataModel *sharedModel = nil;
   static dispatch_once_t onceToken;

   dispatch_once(&onceToken, ^{
       sharedModel = [[DataModel alloc] init];
       //sharedInstance.storeCoordinator = [sharedInstance storeCoordinator];
       //sharedInstance.managedObjectContext = [sharedInstance managedObjectContext];
   });
   return sharedModel;
}

- (void)saveContext {
    NSError *error = nil;
    if (_managedObjectContext != nil) {
        if ([_managedObjectContext hasChanges] && ![_managedObjectContext save:&error]) {
            NSLog(@"error: %@", error.userInfo);
        }
    }
}

#pragma mark - Core Data Stack

- (NSManagedObjectContext *)managedObjectContext {

    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self storeCoordinator];
    if (coordinator != nil) {
        _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
        [_managedObjectContext setPersistentStoreCoordinator: coordinator];
    }
    return _managedObjectContext;
}

- (NSManagedObjectModel *)managedObjectModel {
    if (_managedObjectModel != nil) {
        return _managedObjectModel;
    }
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"DataModel" withExtension:@"momd"];
    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    return _managedObjectModel;
}

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
    if (_storeCoordinator != nil) {
        return _storeCoordinator;
    }

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"model.sqlite"];

    NSError *error = nil;
    _storeCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:_managedObjectModel];
    if (![_storeCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    }

    return _storeCoordinator;
}

#pragma mark Application's Documents Directory

- (NSURL *)applicationDocumentsDirectory {
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}

@end

更新:我意识到这些对象是(null) 的原因。我试图调用 sharedInstance 单例方法,但他们没有正确调用。正在调用 getter 并将进入一个不断调用 getter 的循环。我正确使用了合成变量_managedObjectContext_storeCoordinator。对象现在适当地分配内存并返回引用。谢谢大家的帮助。

【问题讨论】:

  • 你的NSLog返回什么?
  • 嗯,这就是你的答案。您没有 NSManagedObjectContext 的实例。您是如何在 DataModel 类中创建它的?
  • 只需将整个类发布到某个地方,您的 managedObjectContext 方法看起来不错,很可能您的 managedStoreCoordinator 出于某种原因无法打开数据模型。您确定商店协调员的日志文件中没有警告吗?
  • 那么你在ApplicationDelegate中坚持这个类吗?
  • 您是否曾经实例化过您的 DataModel 类?

标签: ios core-data


【解决方案1】:

愚蠢的问题:您的模型实际上命名为 DataModel?

【讨论】:

  • 这应该在 cmets 中。
  • 如果它是原始问题的真正答案,则不是。我在 cmets 中提出问题,直到我们有足够的数据来证明唯一真正的解决方案,无论多么不可能。一定是他的数据模型名称错误(或者我认为)。
  • 同意..错误的数据模型名称也会导致同样的问题,特别是他在创建项目时没有添加核心数据,后来他添加了不同名称的核心数据模型。他从其他名为 DataModel 的地方复制了 Core Data Stack 的所有代码。我今天也做了同样的事情。
【解决方案2】:

在应用程序委托中创建的核心数据堆栈没有任何问题。你从哪里读到过这种情况。

调用 Application Delegate 以获取托管对象上下文当然被认为是糟糕的设计,但大多数人所做的是将托管对象上下文的引用从 Application Delegate 传递给使用它的其他视图控制器.

【讨论】:

  • 看看 MagicalRecord(git 项目)。这让使用 CoreData 非常头疼。
  • 或者在你和 Core Data 之间再增加一层。这是一个见仁见智的问题。
  • 我自己几乎总是像这样设置一个 CoreData 助手单例,这样我就不必到处导入应用程序委托了。这样,我也将 CoreData 导入排除在应用程序委托之外......
猜你喜欢
  • 2012-07-20
  • 2017-10-18
  • 1970-01-01
  • 2015-07-06
  • 2014-09-28
  • 1970-01-01
  • 1970-01-01
  • 2013-12-26
相关资源
最近更新 更多