-2

I have a method that is being called several times. But I need to act only in the very last method call. I tried dispatch_async but didn't work because still is been queue the calls:

-(void)doingSomething:(NSString*)someValue
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [NSThread sleepForTimeInterval:1.0f];
        dispatch_async(dispatch_get_main_queue(), ^{
            // do something with the last call
        });
    });
}

Any of you knows a way to queue the calls and only use the very last call?

I'll really appreciate your help

rmaddy
  • 314,917
  • 42
  • 532
  • 579
user2924482
  • 8,380
  • 23
  • 89
  • 173
  • you want to wait for the last doingSomething call or what do you mean. im afraid I dont get it at all – Daij-Djan Aug 24 '17 at 19:25
  • [Implement a debounced coalesced pattern in Cocoa Touch like layoutsubviews](https://stackoverflow.com/q/28153632) – jscs Aug 26 '17 at 17:08

1 Answers1

2

My suggestion would be to use a dispatch_group. Call dispatch_group_enter before you call dispatch_async, and call dispatch_group_leave and the end of the block that's executed by dispatch_async. Then, after you've enqueued all the blocks, use dispatch_group_notify to schedule the completion block, which will run after all the other dispatch_async blocks have finished.

dispatch_group_t group = dispatch_group_create();

for (...) {
    dispatch_group_enter(group);

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        ...
        dispatch_group_leave(group);
    });
}

dispatch_group_notify(group, dispatch_get_main_queue(), ^{
    // This gets called when all the other blocks have finished
});

Alternatively, you could use an NSOperationQueue instead of libdispatch, and make a completion operation which lists every other operation as a dependency. This does have the disadvantage that the completion operation won't be executed on the main queue, though.

NSOperation *completionOperation = [NSBlockOperation blockOperationWithBlock:^{
    // This gets called when all the other operations have finished
}];

for (...) {
    NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        ...
    }];

    [completionOperation addDependency:operation];
    [operationQueue addOperation:operation];
}

[operationQueue addOperation:completionOperation];
Charles Srstka
  • 16,665
  • 3
  • 34
  • 60
  • How does NSOperationQueue it will only use the last call to the method? – user2924482 Aug 24 '17 at 19:33
  • I added an `NSOperationQueue`-based example as an edit. – Charles Srstka Aug 24 '17 at 19:37
  • From your both examples. All the calls to the method would be executed. Looking into your example implementation how does the last call is the only one executed ? – user2924482 Aug 24 '17 at 20:45
  • Put the part that you only want executed once in the `dispatch_queue_notify` block (for the first example) or `completionOperation` (for the second one). The code you put there will only be executed once, after everything else has completed. – Charles Srstka Aug 24 '17 at 21:52
  • But my point is all the calls are being executed, none of the are been cancel. What I want is just to execute the very last call in the queue – user2924482 Aug 24 '17 at 22:08
  • You can't do that, because as soon as you call `dispatch_async`, the first block may have already started executing. If you use `NSOperationQueue`, you can send the `-cancel` method to the individual `NSOperation` objects, but this will only prevent them from starting; if they've already started, it won't stop them, and there's not really a good way to do that. Most likely, you will need to find a different way to do what you're trying to do. The method I outlined would ensure that the completion block would only run once, at the end. What exactly is it that you're trying to do? – Charles Srstka Aug 24 '17 at 22:13
  • What I'm trying to do is get all the calls to this method and just execute the last one – user2924482 Aug 24 '17 at 22:16
  • 1
    What are you trying to accomplish by doing that? – Charles Srstka Aug 24 '17 at 22:38