Core data UIManagedDocument在ViewDidLoad中创建
经过一些研究,我仍然不确定何时/如何创建UIManagedDocumentCore data UIManagedDocument在ViewDidLoad中创建,core-data,uimanageddocument,Core Data,Uimanageddocument,经过一些研究,我仍然不确定何时/如何创建UIManagedDocument @interface ViewController () @property (strong, nonatomic) UIManagedDocument *document; @end @implementation ViewController - (void) viewWillAppear:(BOOL)animated { [super viewWillAppear:YES]; NSFileManager *f
@interface ViewController ()
@property (strong, nonatomic) UIManagedDocument *document;
@end
@implementation ViewController
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *documentsDirectory = [[fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] firstObject];
NSString *documentName = @"MyDocument";
NSURL *url = [documentsDirectory URLByAppendingPathComponent:documentName];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:[url path]];
if (fileExists) {
[self.document openWithCompletionHandler:^(BOOL success) {
NSLog(@"Exsits dont create again");
if (success) [self documentIsReadyCreateAndObject];
if (!success) NSLog(@"cound not open document at %@", url);
}];
}
else {
// create it
[self.document saveToURL:url forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
NSLog(@"Create it");
if (success) [self documentIsReadyCreateAndObject];
if (!success) NSLog(@"cound not create document at %@", url);
}];
}
}
- (void) documentIsReadyCreateAndObject
{
if (self.document.documentState == UIDocumentStateNormal) {
NSLog(@"document is ready - create obj");
Car *demo = [NSEntityDescription insertNewObjectForEntityForName:@"Car" inManagedObjectContext:self.document.managedObjectContext];
demo.carName = @"xxxxx";
}
else {
NSLog(@"Not ready to go");
}
}
- (void) fetchAndPrint
{
if (self.document.documentState == UIDocumentStateNormal) {
NSLog(@"document is ready - print objs");
NSFetchRequest *request = [[NSFetchRequest alloc]initWithEntityName:@"Car"];
NSArray *results = [self.document.managedObjectContext executeFetchRequest:request error:nil];
for (Car *aLog in results) {
NSLog(@"\nNAME: %@", aLog.carName);
}
}
else {
NSLog(@"Not ready to go");
}
}
@end
查看控制器与应用程序代理
创建UIManagedDocument
的最佳时间取决于具体情况,但我发现在大多数情况下,应用程序的委托是创建该文档的最佳位置。视图控制器实际上不是创建数据库的地方。大多数情况下,您将在应用程序的多个位置使用该数据库,因此创建该数据库并不是一个特定的视图控制器的任务。如果应用程序的设计发生了变化,以至于视图控制器不是屏幕上的第一个控制器,那么您必须将所有代码放入其他视图控制器中
由于核心数据支持的模型通常需要从许多不同的视图控制器访问,因此我使用app委托进行访问。一旦你的应用程序启动,它将创建或打开一个数据库,视图控制器可以立即使用该数据库
这并不意味着你也必须从应用程序代理访问你的文档。关于这是否是一个好的实践,有很多争论,但我更喜欢将文档传递给任何需要的对象,这样它就不会依赖于app委托的模型
大多数时候,你通过<代码> uimaAgDebug 的唯一原因是它的代码> NSCONDATION ObjistValue,所以如果你不需要任何其他文档相关的属性,你可以考虑传递它。另外,如果您只传递一个
NSManagedObject
,您就可以自动访问它的上下文,这样可以减少传递文档的次数
迁移
我将首先回答您的最后一个问题:不,使用传统的核心数据堆栈或
UIManagedDocument
与迁移无关(轻量级或使用映射模型)UIManagedDocument
有一个persistentStoreOptions
属性,可用于为您处理大多数迁移。即使您需要一个映射模型,您也可以创建该模型,将其添加到您的包中,如果您进行了正确的映射,它将为您完成所有工作。在AppDelegate中创建UIManagedDocument,但由于创建是异步的,因此在加载视图时,您不能依赖它准备就绪。因此,您不应该尝试访问viewDidLoad方法中的任何内容。而是在viewController上有一个名为displayData{}的方法,并从UIManagedDocument打开完成处理程序调用它,或者最好在成功创建和/或打开文件后发布通知。最好习惯这种异步方式,因为iCloud广泛使用它。查看此链接了解有关如何实现的更多信息
在viewControllers viewDidLoad方法中添加观察者以接收通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(displayData) name:@"DatabaseReady" object:nil];
在您的viewControllers displayData方法中,获取moc并检索您的数据,您就可以开始了
- (void) displayData
{
self.document = [(AppDelegate *)[[UIApplication sharedApplication] delegate] document];
self.managedObjectContext = self.document.managedObjectContext;
Car *demo = [NSEntityDescription insertNewObjectForEntityForName:@"Car" inManagedObjectContext:self.managedObjectContext];
demo.carName = @"xxxxx ";
}
如果创建失败,我通常还会发布一条(不同的)消息,以便您可以从viewController向用户显示消息。谢谢。将应用程序放入应用程序委托时,应用程序崩溃,这就是问题的主要原因。视图控制器viewDidLoad希望访问MOC(但我假设由于设置在块中,可能会发生延迟),因此viewDidLoad尝试访问MOC,但该MOC尚未设置,因此会崩溃。我不知道如何解决这个问题,使用VC,并将启动代码转换为DocumentsReady是目前为止唯一可行的方法。我仍然会在创建对象时传递整个文档,而不仅仅是上下文。当抓取最终发生时,上下文通常已经准备好了。如果文档没有打开,它可能还没有准备好,我不确定。我只是将所有代码移到viewdidload中,而对象甚至没有被核心数据保存。。。即将放弃此托管文档并使用普通核心数据。@斯密克:请用最新信息更新您的问题code@Smick:现在在视图中打开文档将显示:,太晚了。在应用程序委托中打开它,但将其传递给视图控制器(即使它可能尚未打开)。然后您就可以使用它,因为当视图出现时,它已经打开了。
- (void) displayData
{
self.document = [(AppDelegate *)[[UIApplication sharedApplication] delegate] document];
self.managedObjectContext = self.document.managedObjectContext;
Car *demo = [NSEntityDescription insertNewObjectForEntityForName:@"Car" inManagedObjectContext:self.managedObjectContext];
demo.carName = @"xxxxx ";
}