UIManagedDocument Создание в ViewDidLoad

После некоторых исследований я все еще не уверен, когда и как мне следует создавать свой 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

2 ответа

Решение

Контроллер представления и делегат приложения

Лучшее время для создания вашего UIManagedDocument немного зависит от ситуации, но я считаю, что в большинстве случаев делегат приложения является лучшим местом для этого. Контроллер представления действительно не место для создания базы данных. Большую часть времени вы будете использовать эту базу данных в нескольких местах в вашем приложении, так что на самом деле создание одного ее конкретного контроллера не будет задачей. Если дизайн вашего приложения изменяется так, что контроллер представления не является первым контроллером на экране, вы должны взять весь этот код и поместить его в какой-то другой контроллер представления.

Поскольку для модели с базовыми данными обычно требуется доступ из разных контроллеров представления, для этого я использую делегат приложения. Как только ваше приложение будет запущено, оно создаст или откроет базу данных, которую контроллеры представления могут использовать практически сразу.

Это не означает, что вам также необходимо получить доступ к документу от делегата приложения. Существует много споров о том, является ли это хорошей практикой или нет, но я предпочитаю передавать документ тому объекту, который ему нужен, чтобы он не зависел от делегата приложения для его модели.

Большую часть времени, единственная причина, по которой вы проходите UIManagedDocument для его NSManagedObjectContext, так что вы можете просто передать это, если вам не нужны какие-либо другие свойства, связанные с документами. Кроме того, если вы просто передаете один NSManagedObjectвы автоматически получаете доступ к его контексту, так что это может сократить количество раз, когда вам придется передавать ваш документ.

миграция

Сначала я отвечу на ваш последний вопрос: нет, используя традиционный стек основных данных или UIManagedDocument не имеет значения в отношении миграции (облегченный или использование картографических моделей). UIManagedDocument имеет persistentStoreOptions свойство, которое вы можете использовать для обработки большинства миграций для вас. Даже если вам нужна модель сопоставления, вы можете создать ее, добавить в свой пакет и, если вы сделали правильные сопоставления, она все сделает за вас.

Создайте UIManagedDocument в AppDelegate, но поскольку создание асинхронно, вы не можете полагаться на его готовность при загрузке представления. Поэтому вы не должны пытаться получить доступ к чему-либо в вашем методе viewDidLoad. Вместо этого создайте метод в вашем viewController с именем displayData{} или чем-то еще и вызовите его из обработчика открытого завершения UIManagedDocument, или лучше отправьте уведомление после успешного создания и / или открытия файла. Лучше привыкнуть к этому асинхронному материалу, потому что iCloud широко его использует. Проверьте эту ссылку для получения дополнительной информации о том, как добиться интеграции UIManagedDocument & iCloud.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
   ...

    if (fileExists) {
        [self.document openWithCompletionHandler:^(BOOL success) {

            NSLog(@"Exsits dont create again");
            if (success) {
               [[NSNotificationCenter defaultCenter] postNotificationName:@"DatabaseReady"
                                                        object:self];
            } else {
               NSLog(@"cound not open document at %@", url);
            }
        }];
    }
    else {
        // create it
        [self.document saveToURL:url forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
            NSLog(@"Create it");
            if (success) {
               [[NSNotificationCenter defaultCenter] postNotificationName:@"DatabaseReady"
                                                        object:self];
            } else {
               NSLog(@"cound not create document at %@", url);
            }
        }];
    }
}

Добавьте наблюдателя в свой метод 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.

Другие вопросы по тегам