核心数据:UIManagedDocument或AppDelegate来设置核心数据堆栈?

我有点困惑在哪里设置我的核心数据堆栈。 在Appdelegate或使用UIManagedDocument的共享实例,在这里描述?: http ://adevelopingstory.com/blog/2012/03/core-data-with-a-single-shared-uimanageddocument.html

现在我已经在我的AppDelegate中设置了核心数据堆栈,并且在视图控制器之间传递我的MOC。 但是最好是迁移到UIManagedDocument并创build一个共享实例,所以我不必一直通过MOC? 还因为它更新?

UIManagedDocument用于将数据(通常是文件)同步到iCloud。 它仅与Core Data相关。

核心数据设置通常是在AppDelegate完成的,所以你在那里做什么没有问题。 事实上,如果你使用核心数据创build一个新的项目,那么Xcode模板将如何实现它。

您通常不需要将您的ManagedObjectContext从viewcontroller传递给viewcontroller。 最好创build一个单独的数据访问层,它可以在应用程序的任何地方提供上下文。 在某些情况下,您可能希望为Viewcontroller提供私人MOC,但不是经常使用。

这里有一些代码来创build一个单独的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]; 

这种devise一般运作良好。 NSManagedObjectContext是一个非常轻量级的对象,所以不会有真正的性能损失。 但是,如果您需要在其他线程上执行Core Data,那么devise需要稍微改变一下。 从苹果的文档 :

您必须在将使用它的线程上创build托pipe上下文。 如果您使用NSOperation,请注意,它的init方法在与调用方相同的线程上调用。 因此,您不得在队列的init方法中为队列创build托pipe对象上下文,否则它将与调用方的线程关联。 相反,您应该在主(对于串行队列)或启动(对于并发队列)中创build上下文。

使用线程限制,您不应该在线程之间传递托pipe对象或托pipe对象上下文。 要跨越线程边界从另一个上下文“传递”托pipe对象,您可以:

  • 在接收的托pipe对象上下文中传递其对象ID(objectID)并使用objectWithID:或existingObjectWithID:error:。 相应的pipe理对象必须已经保存 – 不能将新插入的pipe理对象的ID传递给另一个上下文。
  • 在接收上下文中执行提取。

上面的单例方法非常漂亮。 一个更简单的方法是将appDelegate视为一个单例,就是这样。 在你的appDelegate中创build属性,然后以下行的一个版本将检索你想要的。 例如检索moc

 self.managedObjectContext = [(MyAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];