Базовые данные выполняют запрос выборки с помощью обработчика завершения или выполняют в каком-либо другом потоке, отличном от основного потока
В моем приложении для 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