2

在我的 iOS 应用程序中,我使用的是 Core Data。对于表视图列表,我使用 NSFetchedResultsController 和连接到远程存储,我使用 NSIncrementalStore。

我的 FetchedResultsController 上下文具有 MainQueue Cuncurrency 类型。(我无法使用 PrivateQueueCurrencyTYpe 来做到这一点)。

为了解决故障,对于多关系,从我的 IncrementalStore 子类执行 executeFetchResultsCall:withContext:error 方法。

在 executeFetchResults 方法中,如果本地数据库中不可用,我将调用 API(连接到远程服务器)。

myarray = [object representationsForRelationship:@"manyconnection" withParams:nil];

现在我需要将返回的结果数组同步返回给 ExecuteFetchResultsMethod。此操作也应在主线程上执行。

所以我只有一个选项可以从服务器获取结果,这会导致 UI 在指定的睡眠时间内无响应。

-(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;
}

由于上述操作正在主线程上执行,UI 挂起。

为了使 UI 更流畅,我需要在其他一些线程中执行 executeFetchrequest,这是不可能的。

它还期望返回结果数组。

是否有任何选项可以以完成处理程序的方式执行此操作?

或者

任何可以正常工作的替代方法或设计。

非常感谢任何帮助。

4

1 回答 1

1

这是一个骨架,使用 a dispatch_group,假设您正在使用 anNSFetchedResultsController来更新您的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
于 2017-04-03T13:10:48.700 回答