尝试从 iOS 中的 Singleton 类初始化 ManagedObjectContext
Posted
技术标签:
【中文标题】尝试从 iOS 中的 Singleton 类初始化 ManagedObjectContext【英文标题】:Trying to initialize ManagedObjectContext from Singleton class in iOS 【发布时间】:2013-09-25 22:15:24 【问题描述】:我在 ios 中创建了一个单一视图应用程序,它还包含核心数据。我将我的 .xcdatamodel 文件从另一个应用程序移到了我现在正在处理的应用程序中,但我遇到了问题。我所做的是从之前的应用程序中剪切并粘贴代码并将其放在我的 AppDelegate.h/m 文件中:
@interface DBAppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;
@end
还有我的 .m 文件:
@implementation DBAppDelegate
@synthesize managedObjectContext = _managedObjectContext;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
// Override point for customization after application launch.
UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController;
//the line below is what is causing an error
DBViewController *controller = (DBViewController *)navigationController.topViewController;
controller.managedObjectContext = self.managedObjectContext;
return YES;
在我的 .m 文件中,我还包含了 Core Data 的样板代码,该代码也在我之前的应用程序中,但我没有发布。在我的新应用程序中,我正在做的是创建了一个访问层,它还提供了一个 Singleton 实例来访问该层。我在这个类中进行 CRUD 操作,并在 .h 文件中声明了以下属性:
@property (strong, nonatomic) NSManagedObjectContext *managedObjectContext;
@property (strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
@property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController;
目前,我收到以下错误:
“在“DBViewController”类型的对象上找不到属性“managedObjectContext”。我想做的是在我的方法中初始化 managedObjectContext,以允许创建单例实例:
static DB *sharedSingleton = nil;
+ (DB *) sharedInstance
if (sharedSingleton == nil)
sharedSingleton = [[super alloc] init];
return sharedSingleton;
我做错了什么?我意识到我没有在我的 DBViewController 中声明 managedObjectContext 对象,但是我应该用什么来代替这一行?我认为这与我的 Singleton 课程有关,但老实说,我对此一无所知。
【问题讨论】:
syedfa,在决定采用单例方法之前,请考虑阅读这篇文章Core Data singleton manager?。决定内存使用和线程的指标 【参考方案1】:您尝试做的通常被称为“数据存储”单例,这是一种很好的设计模式。我在我的应用程序中做的是有一个名为DataStore
的单例类,你可以随意调用它,使用类方法:
+ (id)sharedStore
static DataStore *sharedStore = nil;
if (!sharedStore)
sharedStore = [[self alloc] init];
return sharedStore;
每当我需要访问数据存储提供的资源时,我都会这样做:
Datastore *ds = [Datastore sharedStore];
为了提供对 Core Data 的访问,我有一个数据存储方法:
+ (NSManagedObjectContext*)managedObjectContext
static NSManagedObjectContext *context = nil;
if(context)
return context;
NSPersistentStoreCoordinator *coordinator = nil;
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Model" withExtension:@"momd"];
NSManagedObjectModel *objectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
if (!coordinator)
coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:objectModel];
if(!coordinator)
return nil;
NSString *storePath = [[self documentsDirectoryPath] stringByAppendingPathComponent:@"datastore.sqlite"];
NSURL *storeURL = [NSURL URLWithString:storePath];
NSError *error;
if (![coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:NULL error:&error])
NSLog(@"Database error: %@", error);
// if you make changes to your model and a database already exists in the app
// you'll get a NSInternalInconsistencyException exception. When the model is updated
// the databasefile must be removed. Remove the database here because it's easy.
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager removeItemAtURL:storeURL error:nil];
//try to add the persistant store one more time. If it still fails then abort
if (![coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:NULL error:&error])
return nil;
context = [[NSManagedObjectContext alloc] init];
[context setPersistentStoreCoordinator:coordinator];
[context setUndoManager:nil];
return context;
如果无法创建 NSManagedObjectContext
,则此方法返回 nil
。这样你只需要这样做:
NSManagedObjectContext *context = [[DataStore sharedStore] managedObjectContext];
当您需要使用 Core Data 时。这可以在viewDidLoad
中完成一次。
编辑:
managedObjectContext
方法使用下面的方法来查找文档目录:
+ (NSString *)documentsDirectoryPath
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
return basePath;
【讨论】:
非常感谢您的及时回复。我使用了您的解决方案,但出现错误:选择器“documentsDirectoryPath”没有已知的类方法。我收到以下错误: NSString storePath = [[self documentsDirectoryPath] stringByAppendingPathComponent:@"datastore.sqlite"];我把这个方法 + (NSManagedObjectContext)managedObjectContext 放在我的 DataStore 类中,对吗? 查看我的编辑。我忘记了我使用一种方法来查找文档目录。 再次感谢您的及时回复。我现在收到 RuntimeException: 'NSInvalidArgumentException', reason: '+entityForName: nil is not a legal NSManagedObjectContext parameter search for entity name'User'。在我的 DataStore 类中,我有方法 addUser,在该方法中我有以下几行: NSManagedObjectContext *context = [[DB sharedInstance] managedObjectContext];//我把这一行放在这里而不是 viewDidLoad 方法。用户 *user = [NSEntityDescription insertNewObjectForEntityForName:@"User" inManagedObjectContext:context]; 作为后续问题,我是否仍需要 AppDelegate 类中的所有样板代码,还是可以完全删除它?只是想知道。 再次感谢。我意识到我的问题是我的 .sqlite 文件丢失了,我必须生成它。您的解决方案帮助我解决了我得到的原始问题,这就是我选择您的答案的原因。我的代码现在可以工作了:-)以上是关于尝试从 iOS 中的 Singleton 类初始化 ManagedObjectContext的主要内容,如果未能解决你的问题,请参考以下文章