【发布时间】: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 类?