Note that there are some explanatory texts on larger screens.

plurals
  1. PONSInvocationOperation callback too soon
    primarykey
    data
    text
    <p>I know similar questions have been asked a few times, but I'm struggling to get my head around how this particular problem can be solved. So far, everything I've done has been carried out on the main tread. I now find that I need to perform an operation which will take some time, and I want to add a HUD to my display for the duration of the operation and fade it away when the operation is complete.</p> <p>After reading a lot about GCD (and getting quite confused), I decided the simplest way to go would be to call my time consuming method with an NSInvocationOperation and add it to a newly created NSOperationQueue. This is what I have:</p> <pre><code> [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]; </code></pre> <p>I would expect this to show the HUD, start drawing the dots on the map, and then <em>once that operation is finished</em>, fade away the HUD.</p> <p>Instead, it shows the HUD, starts drawing the dots on the map, and fades way the HUD while still drawing the dots. According to my NSLogs, there is about a quarter of a second delay before calling the method to fade the HUD. Meanwhile the drawing of the dots continues for another few seconds.</p> <p>What can I do to make it wait until the drawing on the map is complete before fading away the HUD?</p> <p>Thanks</p> <p>EDITED TO ADD:</p> <p>I'm almost getting success after making the following changes:</p> <pre><code> 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]; </code></pre> <p>Strangely, it seems to be calling timeConsumingOperation first, then showLoadingConfirmation, then fadeConfirmation. This is according to my NSLogs, which are fired within those methods.</p> <p>The behaviour I'm seeing on screen is this: the dots are drawn and the map adjusts it's zoom accordingly (part of the timeConsumingOperation), then the HUD appears on screen, then nothing. All three NSLogs appear instantly, even though showLoadingConfirmation does not happen until timeConsumingOperation is complete and fadeConfirmation does not seem to happen at all.</p> <p>This seems very strange, but also seems to suggest that there is a way to make something happen at the completion of timeConsumingOperation.</p> <p>I tried adding this:</p> <pre><code>[operationQueue setMaxConcurrentOperationCount:1]; </code></pre> <p>and also this:</p> <pre><code>[showHud setQueuePriority:NSOperationQueuePriorityVeryHigh]; [operation setQueuePriority:NSOperationQueuePriorityNormal]; [hideHud setQueuePriority:NSOperationQueuePriorityVeryLow]; </code></pre> <p>but they don't seem to make any difference.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload