How to return outer function from inside async inner function in Objective-C

前端 未结 2 1397
一向
一向 2020-12-20 09:01

I want to return from outer function from inside async inner function. In swift, I would have used completion handler for this purpose which would escape from function. But

相关标签:
2条回答
  • 2020-12-20 09:21

    Easier is just to call another function that tells it's completed.

    -(void)chosenFrom:(NSDictionary<NSString *,id> *)info{
    
        [self asyncCode:info withCompletion:^(NSData *imageData) {
            if(imageData) {
                 [self completedAsync:imageData];
            }
        }];
    
    }
    
    -(void)completedAsync:(NSData*) imageData {
      // do your thang.
    }
    
    0 讨论(0)
  • 2020-12-20 09:33

    It seems you've asked the same question twice in different ways and people are stuck helping you. This isn't an answer as such, as I don't really know the question, but hopefully this might either help you find the answer or ask the question differently so people can help you.

    Let's start with your statement:

    escaping means returning from function just like return statement

    and you've referred to using @escaping in Swift. While the term escaping might be used in some language to refer to what you say it is not what it means in Swift at all.

    It is reasonable to be confused over what it means in Swift, as it essentially makes what could/should be a hidden compiler optimisation visible to the programmer in the language. The definition in Swift is:

    A closure is said toescape a function when the closure is passed as an argument to the function, but is called after the function returns. When you declare a function that takes a closure as one of its parameters, you can write @escaping before the parameter's type to indicate that the close is allowed to escape.

    One way that a closure can escape is by being stored in a variable that is defined outside the function. As an example, many functions that start an asynchronous operation take a closure argument as a completion handler. The function returns after it starts the operation, but the closure isn't called until the operation is completed – the closure needs to escape, to be called later.

    The Swift Programming Language (Swift 4.2)

    What this is telling you is that @escaping affects how the closure may be stored and used, not what the closure itself actually does when called. When invoked a closure does the same operations regardless of whether it is marked as @escaping or not.

    Moving on, the example used to illustrate @escaping has relevance to what appears to be your situation – you apparently wish to have a method, say A, initiate an asynchronous operation, say *B**, passing it a closure, say C, which when invoked later will cause A to return. That is impossible as when C is invade there is no invocation of A to return from. Look at the example again, emphasis added:

    One way that a closure can escape is by being stored in a variable that is defined outside the function. As an example, many functions that start an asynchronous operation take a closure argument as a completion handler. The function returns after it starts the operation, but the closure isn't called until the operation is completed

    After A has started B it returns, by the time C is invoked the invocation of A which started B has already returned. You are apparently asking for the impossible!

    So what might be you trying to do?

    Your intent might be to make A and the asynchronous operation it starts B appear as a single synchronous unit and for A not to return until B has done its work.

    There are rare cases when wrapping asynchronicity as synchronous operations is required, and many more cases where people attempt to do it to make asynchronicity easier to handle but who end up destroying all the benefits of asynchronicity in the process. To do such wrapping often looks deceptively simple; but unless you have a good grasp of the GCD block model, semaphores, threads, blocking and deadlock it holds traps for the unwary.

    If your intent is too try to wrap asynchronicity the better route is to embrace it instead, in your case figure out how to make your closure C do what is needed when it has been called asynchronously longer after the corresponding invocation of your method A has terminated and is no more. Thirty years ago asynchronicity was the esoteric end of day-to-day programming, today it is at its core, you need to understand and use it.

    If after trying to embrace asynchronicity you decide you have one of those rare cases when it needs to hidden inside of a synchronous wrapper do a search on SO for asynchronous, semaphore etc. and you should find a solution.

    If you get stuck with asynchronicity, or are actually asking about something completely different, ask a new question, show what you've done/tried/etc., and someone will undoubtedly help you take the next step.

    HTH

    0 讨论(0)
提交回复
热议问题