NSFetchRequest извлекает ноль совпадений сущности из базы данных, созданной с использованием UIManagedDocument

Я использую статью Джастина Дрисколла о базовых данных с UIManagedDocument в одноэлементном шаблоне, чтобы настроить его для UITabViewController. Я запускаю приложение на симуляторе. Впервые работает нормально. База данных создана успешно, и я вижу данные в контроллере таблиц для каждой вкладки. Но когда я перезапускаю свое приложение, табличные представления пусты, потому что NSFetchRequest выбирает 0 совпадений для объекта. Тот же запрос на выборку возвращает правильный результат во время первого запуска.

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

То, как я делаю загрузку данных, как видно из кода. Метод fetchDataIntoDocument выполняет начальную загрузку данных.

// Обработчик документов Singleton Class

 -(void) performWithDocument:(OnDocumentReady)onDocumentReady {

     void (^OnDocumentDidLoad)(BOOL) = ^(BOOL Success) {
              onDocumentReady(self.document);
     };

    if (![[NSFileManager defaultManager] fileExistsAtPath:[self.document.fileURL path]]) {
        **[self fetchDataIntoDocument:self.document];**  
        [self.document saveToURL:self.document.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:OnDocumentDidLoad];
    } else if (self.document.documentState == UIDocumentStateClosed) {
        [self.document openWithCompletionHandler:OnDocumentDidLoad];
    } else if (self.document.documentState == UIDocumentStateNormal) {  
        OnDocumentDidLoad(YES);
    }
 }

 -(void)fetchDataIntoDocument:(UIManagedDocument *)document {

       MyEntityDataController *dc= [[MyEntityDataController alloc] init];
       NSDictionary *entityInfo  =[dc getEntityInfo];
       [document.managedObjectContext performBlock:^{
                 [Entity createEntityWithInfo:entityInfo   inManagedObjectContext:document.managedObjectContext];
       }];
 }

Мой класс TableViewController

 -(void)viewWillAppear:(BOOL)animated {

      [super viewWillAppear:animated];
      if (!self.databaseDocument) {
           [[LTDatabaseDocumentHandler sharedDatabaseDocumentHandler] performWithDocument:^    (UIManagedDocument *document) {
           self.databaseDocument = document;
           [self populateTableViewArrayFromDocument:self.databaseDocument];
           }];
      }
  } 

В populateTableViewArrayFromDocument я выполняю свой запрос на выборку

  -(void)populateTableViewArrayFromDocument:(UIManagedDocument *)document
{
       NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Entity2"];
       NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:NO];
     NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
      [request setSortDescriptors:sortDescriptors];

     NSError *error = nil;
     NSArray *matches = [self.databaseDocument.managedObjectContext  executeFetchRequest:request error:&error];
     NSLog(@" matches count for Entity2 %d", matches.count);
     for (Entity2 *entity2 in matches) {
        //do stuff with data and add it to tableview array
     }
    }

1 ответ

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

Вот код, который я использую, чтобы убедиться, что документ готов:

 if ([[NSFileManager defaultManager] fileExistsAtPath:[_URLDocument path]]) {
        [_managedDocument openWithCompletionHandler:^(BOOL success){
            [self ready]
            if (!success) {
                // Handle the error.
            }
        }];
 } 

Надеюсь, это поможет, ура!

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