Базовые данные выполняют запрос выборки с помощью обработчика завершения или выполняют в каком-либо другом потоке, отличном от основного потока

В моем приложении для iOS я использую Core Data. Для просмотра таблицы я использую NSFetchedResultsController, а для подключения к удаленному хранилищу я использую NSIncrementalStore.

Мой контекст FetchedResultsController имеет тип MainQueue Cuncurrency (я не мог сделать это с PrivateQueueCurrencyTYpe).

Для разрешения Fault для многих отношений выполняется метод executeFetchResultsCall:withContext:error из моего подкласса IncrementalStore.

Внутри метода executeFetchResults я вызову API (подключение к удаленному серверу), если он не доступен в моей локальной базе данных.

myarray = [представления объекта ForRelationship:@"manyconnection" withParams:nil];

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

Поэтому у меня есть только одна опция для получения результатов с сервера, что приводит к тому, что пользовательский интерфейс не отвечает в течение указанного времени ожидания.

-(RequestResult*)makeSyncJsonRequest{

    __block RequestResult *retResult = [[RequestResult alloc] init];
    __block BOOL block = YES;

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

   dispatch_group_t group = dispatch_group_create();

   void (^resultBlock)(RequestResult*) = ^(RequestResult* result){
      if(!retResult.error)
          retResult = result;
      block = NO;
      dispatch_group_leave(group);
  };

  // Add a task to the group
 dispatch_group_async(group, queue, ^{
       // Some asynchronous work

       dispatch_group_enter(group);
       [self makeAsyncJsonRequestWithBlock:resultBlock];
 });

 // Do some other work while the tasks execute.
 // When you cannot make any more forward progress,
 // wait on the group to block the current thread.    
 dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
 return retResult;
}

Поскольку вышеуказанная операция выполняется в основном потоке, пользовательский интерфейс зависает.

Чтобы сделать пользовательский интерфейс более плавным, мне нужно выполнить executeFetchrequest в каком-то другом потоке, что невозможно.

Это также ожидает массив результатов в ответ.

Есть ли возможность выполнить это как обработчик завершения?

или же

Любые альтернативные методы или дизайн для работы это правильно.

Любая помощь высоко ценится.

1 ответ

Это скелет, используя dispatch_groupпри условии, что вы используете NSFetchedResultsController обновить свой UITableView:

@implementation ViewController

    - (void)viewDidLoad {
        [super viewDidLoad];
        // do your setup (FetchedResultsController and such)
        [self syncData];
    }

    - (void)syncData
    {
        NSArray<Entity*> *results = [self fetchData];
        BOOL needsUpdateFromServer = YES; // check your results and set this bool accordingly

        if (!needsUpdateFromServer) {
            return;
        }

        __block ServerResponse *fromServer = nil;
        __block dispatch_group_t group = dispatch_group_create();
        dispatch_group_enter(group);
        [self loadDataFromServer:^(ServerResponse *response) {
            fromServer = response;
            dispatch_group_leave(group);
        }];

        dispatch_group_notify(group,dispatch_get_main_queue(),^{
            [self persistData:fromServer];
            /*
             According to our discussion, you are using an NSFetchedResultsController. 
             So your tableView should update automatically after persisting the data.
             */
        }); 
    }

    - (void)loadDataFromServer:(void (^)(ServerResponse *response))completion
    {
        // [someDownloadService downloadDataFromServerInBackgroundWithCompletion:^(ServerResponse* response){
            dispatch_async(dispatch_get_main_queue(), ^{
                completion(response);
            });
        // }];
    }

    - (NSArray<Entity*>*)fetchData
    {
        NSArray<Entity*> *results = nil;
        // fetch from core data and return it
        return results;
    }

    - (void)persistData:(NSArray<ServerResponse*> *)serverResponses
    {
        // parse whatever you get from server
        // ... and persist it using Core Data
    }

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