Я знаю, что подобные вопросы задавались несколько раз, но я изо всех сил пытаюсь понять, как можно решить эту конкретную проблему. До сих пор все, что я делал, выполнялось на основном протекторе. Теперь я обнаружил, что мне нужно выполнить операцию, которая займет некоторое время, и я хочу добавить HUD на свой дисплей на время операции и исчезнуть, когда операция будет завершена.
Много прочитав о GCD (и сильно запутавшись), я решил, что самым простым способом будет вызвать мой трудоемкий метод с помощью NSInvocationOperation и добавить его во вновь созданный NSOperationQueue. Вот что у меня есть:
[self showLoadingConfirmation]; // puts HUD on screen
// this bit takes a while to draw a large number of dots on a MKMapView
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self
selector:@selector(timeConsumingOperation:)
object:[self lotsOfDataFromManagedObject]];
// this fades the HUD away and removes it from the superview
[operation setCompletionBlock:^{ [self performSelectorOnMainThread:@selector(fadeConfirmation:) withObject:loadingView waitUntilDone:YES]; }];
NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
[operationQueue addOperation:operation];
Я ожидаю, что это покажет HUD, начнет рисовать точки на карте, а затем как только эта операция будет завершена, исчезнет HUD.
Вместо этого он показывает HUD, начинает рисовать точки на карте и затемняет HUD, продолжая рисовать точки. Согласно моим NSLogs, есть задержка около четверти секунды перед вызовом метода для затухания HUD. Тем временем рисование точек продолжается еще несколько секунд.
Что я могу сделать, чтобы он ждал завершения рисования на карте, прежде чем исчезать HUD?
Спасибо
ОТРЕДАКТИРОВАНО ДОБАВИТЬ:
Я почти добиваюсь успеха после внесения следующих изменений:
NSInvocationOperation *showHud = [[NSInvocationOperation alloc] initWithTarget:self
selector:@selector(showLoadingConfirmation)
object:nil];
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self
selector:@selector(timeConsumingOperation:)
object:[self lotsOfDataFromManagedObject]];
NSInvocationOperation *hideHud = [[NSInvocationOperation alloc] initWithTarget:self
selector:@selector(fadeConfirmation:)
object:loadingView];
NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
NSArray *operations = [NSArray arrayWithObjects:showHud, operation, hideHud, nil];
[operationQueue addOperations:operations waitUntilFinished:YES];
Как ни странно, он сначала вызывает timeConsumingOperation, затем showLoadingConfirmation, затем fadeConfirmation. Это согласно моим NSLogs, которые запускаются этими методами.
Поведение, которое я вижу на экране, таково: точки рисуются, и карта соответствующим образом регулирует масштаб (часть timeConsumingOperation), затем на экране появляется HUD, а затем ничего. Все три NSLog появляются мгновенно, хотя showLoadingConfirmation не происходит до тех пор, пока timeConsumingOperation не завершится, а fadeConfirmation, похоже, вообще не происходит.
Это кажется очень странным, но также предполагает, что есть способ заставить что-то произойти по завершении timeConsumingOperation.
Я попытался добавить это:
[operationQueue setMaxConcurrentOperationCount:1];
а еще это:
[showHud setQueuePriority:NSOperationQueuePriorityVeryHigh];
[operation setQueuePriority:NSOperationQueuePriorityNormal];
[hideHud setQueuePriority:NSOperationQueuePriorityVeryLow];
но они, кажется, не имеют никакого значения.