2

I'm doing some customization in iOS, I'm subclassing a system class that executes a method asynchronously (presumably with dispatch_async) Sample code:

-(void)originalAsyncMethod {
    [super originalAsyncMethod];
    dispatch_async(dispatch_get_main_queue(), ^{
      //do something that needs to happen just after originalAsyncMethod finishes executing
    });
  }

Is there a way I can make sure my custom code runs AFTER the async super method is executed?

2
  • 1
    In general, without access to the super class source, you cannot do this (at least not reliably and robustly). Perhaps you could tell us what the business problem is and what the super class is, and we might be able to propose other approaches. Commented Aug 19, 2013 at 16:17
  • 1
    I do not know of a system class which has an asynchronous method WITHOUT any means to signal completion to the call-site. So, IFF there is a completion block or a delegate method (I'm pretty sure there is) just invoke your method after receiving the completion event. But unless we know for sure there is some kind of completion handler, we cannot suggest a solution and any answer will be just blah blah. So, I can just emphasize what @Rob already said above. Commented Aug 19, 2013 at 17:35

1 Answer 1

2

It's unclear to me wether this would be possible based on your question, but if you have direct access to the implementation of super, then this shouldn't be to hard to achieve.

First, assuming that you have access to the super class and that the super implementation also dispatches asynchronously to the main queue, then you don't actually have to do anything to get this working expectedly. When you use dispatch_get_main_queue() you're adding your dispatch block to the end of a serial queue on the main thread that is executed in FIFO (first in first out) order.

The second option is also pretty heavily reliant on having access to the super implementation, as it would require you manually create your own dispatch queue to execute tasks on. I think it goes without saying that if you use a serial dispatch queue then you have FIFO ordering in this queue same as you dispatch_get_main_queue(), only you wouldn't have to execute on the main thread.

And the last option I can think of wouldn't necessarily require you to modify the super class, but would require you to know the queue on which super was executing. (and still might not work right if it's a global queue) By using a dispatch_barrier, you could allow your super implementation to execute asynchronously on a concurrent queue knowing that the subclass dispatch block has also been added to the queue (via dispatch_barrier), and will be executed once the super dispatch (and any other previous submissions to the queue) has completed.

Quoting the docs

A dispatch barrier allows you to create a synchronization point within a concurrent dispatch queue. When it encounters a barrier, a concurrent queue delays the execution of the barrier block (or any further blocks) until all blocks submitted before the barrier finish executing. At that point, the barrier block executes by itself. Upon completion, the queue resumes its normal execution behavior.

Sign up to request clarification or add additional context in comments.

6 Comments

I don't have access to the super class implementation, and only assume it is dispatched to the main queue because it changes the UI hierarchy (adds a new key UIWindow). Can the third option be implemented without source to super implementation ?
@nobre Well sorry I couldn't be more help, but that's all I really know about it. And just something to keep in mind, but the super class may be dispatching to a queue other than the main queue and then only returning to the main queue at the end of execution to make the UI changes.
As @0x7fffffff says, you're going to have to know what queue originalAsyncMethod uses. Without that information, and in general without information about the internal implementation details of originalAsyncMethod, there is no generic way to know when some other method is "done" if "done" includes running things asynchronously. Getting so tied to internal implementation details of Apple code is very fragile, and suggests that you should refocus on your design.
@RobNapier , this is just a proof of concept that works on a single call, but fails in successive calls, because the customization is applied too early on the second call, hence the desire to wait the async super call ends
@0x7fffffff , according to the docs the barrier only works for a queue created by the developer, using it for any of the system queues behaves as if dispatch_async was called
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.