Знам, че подобни въпроси са задавани няколко пъти, но се боря да разбера как може да се реши този конкретен проблем. Досега всичко, което съм правил, е извършено на основния протектор. Сега откривам, че трябва да извърша операция, която ще отнеме известно време, и искам да добавя 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 се появява на екрана, след това нищо. И трите NSLogs се появяват незабавно, въпреки че showLoadingConfirmation не се случва, докато timeConsumingOperation не приключи, а fadeConfirmation не изглежда да се случва изобщо.
Това изглежда много странно, но също така изглежда предполага, че има начин да накарате нещо да се случи при завършване на timeConsumingOperation.
Опитах се да добавя това:
[operationQueue setMaxConcurrentOperationCount:1];
а също и това:
[showHud setQueuePriority:NSOperationQueuePriorityVeryHigh];
[operation setQueuePriority:NSOperationQueuePriorityNormal];
[hideHud setQueuePriority:NSOperationQueuePriorityVeryLow];
но те изглежда не правят никаква разлика.