If the SDKPlatform sends its termination block back to the main queue, your approach of blocking the main thread until the termination block is called is likely to slow down, and you are unlikely to be able to do this. But this semaphore approach is to block the main thread so that you can make the asynchronous method as synchronous, in any case, impractical. In fact, you should use asynchronous templates and use completion block methods in your own code.
This link, How to wait for the asynchronous dispatch to complete? , illustrates how semaphores can be used to synchronously run an asynchronous task. Unfortunately, this technique is misused with alarming frequency. In particular, in this case, the semaphore is not a suitable template in your script, because the semaphore template blocks the main thread, which we should never do in the application.
As a background, the semaphore method works great in the script discussed in this other thread, because this is a completely different technical issue. It is used in a special situation in the framework of testing, and not in the application, and in a situation where (a) the test itself should occur in the main thread; (b) for the testing structure to function, it must block the main thread until the completion of the asynchronous task. In addition, it also works in this test scenario, since the completion block is not executed in the main queue, avoiding the deadlock problem that you encountered.
None of these three conditions are true in your case. Using semaphore technique in your situation is impractical.
So step back and look at your problem. I assume you have a method that looks like this:
- (BOOL) login { dispatch_semaphore_t sema = dispatch_semaphore_create(0); __block BOOL _isLogined; __block BOOL _isCallback = NO; dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(queue, ^ {
Even if you did not have a dead end problem, this is still the wrong template. What you probably want is something like:
- (void)loginWithCompletionHandler:(void (^)(BOOL isLoggedIn))completionHandler { [[SDKPlatform defaultPlatform] SDKIsLogined:^(BOOL isLoggedIn){ if (completionHandler) { completionHandler(isLoggedIn); } }]; }
Note. This function has a return type of void , but the isLoggedIn condition isLoggedIn returned by the completion block (and should only be used in the completion block, for example:
[self loginWithCompletionHandler:^(BOOL isLoggedIn) {