如何从Objective-C中的异步内部函数内部返回外部函数 [英] How to return outer function from inside async inner function in Objective-C

查看:75
本文介绍了如何从Objective-C中的异步内部函数内部返回外部函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从异步内部函数内部的外部函数返回. 很快,我会为此目的使用完成处理程序,该处理程序会从函数中逸出.但是在Objective-C中,完成处理程序实际上不会从函数中返回:

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 in Objective-C, completion handler won't actually return from function:

我的功能如下:

-(void)chosenFrom:(NSDictionary<NSString *,id> *)info{

    [self asyncCode:info withCompletion:^(NSData *imageData) {
        if(imageData) {
             // I want to return from  chosenFrom function ***inside here.***
        }
    }];

// This is to illustrate  completion handler don't escape
[self checkCompletionEscaping:^(NSString * lad) {
    NSLog(@"Check me %@", lad);// It would print all 3 lines below.
}];
}

-(void) checkCompletionEscaping:(void(^)(NSString * lad)) completion {
completion(@"Hello"); // completion handler should've escaped from func.
completion(@"Shivam");
completion(@"How are you");
}

如果我要使用Swift,我可以使用完成处理程序从内部函数内部轻松地从外部函数返回:

If I were to use Swift, I could have easily returned from outer function from inside inner function using completion handler:

private func getHistoryKeys(searchterm: String, completion: @escaping () -> ()) {
  let url = PubmedAPI.createEsearchURL(searchString: searchterm)
  let task = session.dataTask(with: url) { (data, response, error) in
   if let error = error {
      completion() // This would work as return
   } else {
      completion() // Same as return
   }
  }
 task.resume()
}

PS:转义表示像return语句一样从函数中返回.

PS: escaping means returning from function just like return statement.

推荐答案

似乎您以不同的方式问了同样的问题两次,人们一直在帮助您.这并不是一个答案,因为我并不真正知道这个问题,但是希望这可以帮助您找到答案或提出不同的问题,以便人们可以为您提供帮助.

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:

转义意味着从函数中返回,就像return语句

escaping means returning from function just like return statement

,您已经在Swift中使用@escaping进行了引用.虽然转义一词在某种语言中可能用来指代您所说的,但这根本不是Swift中的意思.

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.

对它在Swift中的含义感到困惑是合理的,因为它实质上使程序员可能/应该用该语言看到隐藏的编译器优化. Swift中的定义是:

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:

当闭包作为参数传递给函数时,闭包被称为转义,但是在函数返回后被调用.声明一个将闭包作为其参数之一的函数时,可以在参数的类型之前写@escaping,以指示允许转义闭包.

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.

Swift编程语言(Swift 4.2)

这告诉您的是@escaping影响闭包的存储和使用方式,而不影响闭包本身在调用时的实际作用.调用闭包时,无论是否将其标记为@escaping,它都会执行相同的操作.

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.

继续,用于说明@escaping的示例与您所处的情况有关–您显然希望有一个方法,例如 A ,启动一个异步操作,例如* B **,将其传递给闭包,例如 C ,稍后调用该闭包将导致 A 返回.这是不可能的,因为 C 被入侵时,没有 A 的调用要返回.再次查看示例,重点是添加:

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

A 启动 B 后,它会返回,直到调用 C 时调用 B 开头的> A 已返回.您显然是在要求不可能!

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!

那你想做什么?

您的意图可能是使 A 及其开始于 B 的异步操作显示为单个 synchronous 单元,并且表示 A 直到 B 完成工作后才返回.

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.

在很多情况下,由于需要同步操作而包装了异步性,因此还有很多情况,人们试图这样做以使异步性更易于处理,但最终却破坏了异步性的所有好处.过程.进行这种包装通常看起来很简单.但是除非您对 GCD块模型信号量线程阻止死锁,它为无意识的人保留了陷阱.

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.

如果您的意图太过尝试包装异步性,那么更好的方法是采用异步方式,在您的情况下,请弄清楚如何使闭包 C 能够在异步调用更长的时间做所需的工作在您的方法 A 的相应调用终止并且不再存在之后.三十年前,异步是日常编程的深奥终结,如今,它已成为其核心,您需要了解和使用它.

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.

如果尝试拥抱异步之后,您确定自己有一种罕见的情况需要隐藏在同步包装器中,请在SO上搜索 asynchronous semaphore 等.您应该找到解决方案.

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

这篇关于如何从Objective-C中的异步内部函数内部返回外部函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆