Iphone 核心数据:用于设置核心数据堆栈的UIManagedDocument或AppDelegate?
我对在哪里设置核心数据堆栈有点困惑。在Appdelegate中,或使用UIManagedDocument的共享实例,如下所述:Iphone 核心数据:用于设置核心数据堆栈的UIManagedDocument或AppDelegate?,iphone,ios,objective-c,core-data,sdk,Iphone,Ios,Objective C,Core Data,Sdk,我对在哪里设置核心数据堆栈有点困惑。在Appdelegate中,或使用UIManagedDocument的共享实例,如下所述: 现在,我在AppDelegate中设置了by core数据堆栈,并在ViewController之间传递MOC。但是迁移到UIManagedDocument并创建一个共享实例是否更好,这样我就不必一直通过MOC了?另外,因为它较新的UIManagedDocument用于将数据(通常是文件)同步到iCloud。它只与核心数据有切点关系 核心数据设置通常在AppDelega
现在,我在AppDelegate中设置了by core数据堆栈,并在ViewController之间传递MOC。但是迁移到UIManagedDocument并创建一个共享实例是否更好,这样我就不必一直通过MOC了?另外,因为它较新的UIManagedDocument用于将数据(通常是文件)同步到iCloud。它只与核心数据有切点关系 核心数据设置通常在
AppDelegate
中完成,因此您在那里所做的没有任何错误。事实上,如果您使用核心数据创建一个新项目,那么Xcode模板就是这样做的
通常不需要将ManagedObjectContext
从viewcontroller传递到viewcontroller。最好创建一个单例数据访问层,它可以在应用程序中的任何位置提供上下文。在某些情况下,您可能希望为viewcontroller使用专用MOC,但不太常见
下面是一些创建单例DataAccessLayer的代码:
DataAccessLayer.h
@interface DataAccessLayer : NSObject
//Saves the Data Model onto the DB
- (void)saveContext;
//DataAccessLayer singleton instance shared across application
+ (id) sharedInstance;
+ (void)disposeInstance;
// Returns the managed object context for the application.
// If the context doesn't already exist, it is created and bound
// to the persistent store coordinator for the application.
+ (NSManagedObjectContext *)context;
@end
DataAccessLayer.m
#import "DataAccessLayer.h"
//static instance for singleton implementation
static DataAccessLayer __strong *manager = nil;
//Private instance methods/properties
@interface DataAccessLayer ()
// Returns the managed object context for the application.
// If the context doesn't already exist, it is created and
// bound to the persistent store coordinator for the application.
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
// Returns the managed object model for the application.
// If the model doesn't already exist, it is created from the application's model.
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
// Returns the persistent store coordinator for the application.
// If the coordinator doesn't already exist, it is created and the application's
// store added to it.
@property (readonly,strong,nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
// Returns the URL to the application's Documents directory.
- (NSURL *)applicationDocumentsDirectory;
@end
@implementation DataAccessLayer
@synthesize managedObjectContext = __managedObjectContext;
@synthesize managedObjectModel = __managedObjectModel;
@synthesize persistentStoreCoordinator = __persistentStoreCoordinator;
//DataAccessLayer singleton instance shared across application
+ (id)sharedInstance
{
@synchronized(self)
{
if (manager == nil)
manager = [[self alloc] init];
}
return manager;
}
+ (void)disposeInstance
{
@synchronized(self)
{
manager = nil;
}
}
+(NSManagedObjectContext *)context
{
return [[DataAccessLayer sharedInstance] managedObjectContext];
}
//Saves the Data Model onto the DB
- (void)saveContext
{
NSError *error = nil;
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil)
{
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error])
{
//Need to come up with a better error management here.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
}
// Returns the managed object context for the application.
// If the context doesn't already exist, it is created and
// bound to the persistent store coordinator for the application.
- (NSManagedObjectContext *)managedObjectContext
{
if (__managedObjectContext != nil)
return __managedObjectContext;
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil)
{
__managedObjectContext = [[NSManagedObjectContext alloc] init];
[__managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return __managedObjectContext;
}
// Returns the managed object model for the application.
// If the model doesn't already exist, it is created from the
// application's model.
- (NSManagedObjectModel *)managedObjectModel
{
if (__managedObjectModel != nil)
return __managedObjectModel;
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Model"
withExtension:@"momd"];
__managedObjectModel = [[NSManagedObjectModel alloc]
initWithContentsOfURL:modelURL];
return __managedObjectModel;
}
// Returns the persistent store coordinator for the application.
// If the coordinator doesn't already exist, it is created and the
// application's store added to it.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (__persistentStoreCoordinator != nil)
return __persistentStoreCoordinator;
NSURL *storeURL = [[self applicationDocumentsDirectory]
URLByAppendingPathComponent:@"MyData.sqlite"];
NSError *error = nil;
__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc]
initWithManagedObjectModel:[self managedObjectModel]];
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil URL:storeURL options:nil error:&error])
{
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return __persistentStoreCoordinator;
}
// Returns the URL to the application's Documents directory.
- (NSURL *)applicationDocumentsDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory
inDomains:NSUserDomainMask] lastObject];
}
@end
在需要上下文的任何时候,您都可以使用以下方法获取上下文:
NSManagedObjectContext *context = [DataAccessLayer context];
这种设计通常效果很好NSManagedObjectContext
是一个非常轻量级的对象,因此不存在真正的性能损失。但是,如果您需要在其他线程上执行核心数据,那么设计需要做一些更改。发件人:
您必须在要创建托管上下文的线程上创建托管上下文
用过。如果使用NSOperation,请注意其init方法是在
与调用方相同的线程。因此,您不能创建
队列的init方法中队列的托管对象上下文,
否则它将与调用方的线程相关联。相反,你
应该在main(对于串行队列)或start(对于串行队列)中创建上下文
并发队列)
使用线程限制时,不应传递托管对象或
线程之间的托管对象上下文。“传递”托管对象的步骤
从一个上下文到另一个线程边界,您可以:
- 传递其对象ID(objectID)并使用objectWithID:或existingObjectWithID:错误: 在接收托管对象上下文上。相应的托管对象必须具有 如果已保存,则无法将新插入的托管对象的ID传递给其他上下文
- 在接收上下文上执行提取
上面的单例方法非常灵活。一种简单得多的方法是将appDelegate视为一个单例,事实就是这样。在appDelegate中创建属性,然后以下行的版本将检索您想要的属性。例如,检索moc
self.managedObjectContext = [(MyAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
如果我没记错的话,您确实需要担心跨线程调用。。。我想。这意味着,虽然您可以从任何线程访问它,但不能在线程之间共享上下文。《苹果》可能是一本有用的读物。非常感谢你清晰而快速的回答。。谢谢你,Joushua也:)。。。。我只是觉得用核心数据设置创建一个单例是不好的做法。。但这让“生活”变得容易多了,所有MOC的通过都是“可怕的”:戴普,@Joshua有一个很好的观点。如果您需要执行异步调用(对于大型数据加载之类的事情),那么您需要为这些调用调整一些设计。这仍然很简单,但不像单身汉那么简单。如果有人感兴趣,我会在回答中记下这一点。我一直在同一个页面上,从来没有使用过UIManagedDocument,直到我在iTunesU上观看了最新的斯坦福课程,他们在那里使用UIManagedDocument。我对这件事的愤怒让我想到了这个问题。。。