Core data UIManagedDocument在ViewDidLoad中创建

Core 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

经过一些研究,我仍然不确定何时/如何创建UIManagedDocument

@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 ";
}