如何从Objective-C中的异步内部函数内部返回外部函数

问题描述 投票:0回答:2

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

我的功能如下:

-(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,我可以使用完成处理程序轻松地从内部函数内部返回外部函数:

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语句一样从函数返回。

objective-c completionhandler
2个回答
0
投票

更容易调用另一个告诉它已完成的函数。

-(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
投票

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

让我们从您的发言开始:

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

您已经在Swift中使用@escaping进行了引用。尽管术语转义在某些语言中可能用来指代您所说的内容,但这根本不是Swift中的意思。

混淆它在Swift中的含义是合理的,因为它本质上使程序员可能/应该在该语言中看到隐藏的编译器优化。 Swift中的定义是:

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

闭包可以逃脱的一种方法是将其存储在函数外部定义的变量中。例如,许多启动异步操作的函数都将闭包参数用作完成处理程序。该函数在开始操作后返回,但是直到操作完成后才调用闭包–闭包需要转义,稍后再调用。

Swift编程语言(Swift 4.2)

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

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

闭包可以逃脱的一种方法是将其存储在函数外部定义的变量中。例如,许多启动异步操作的函数都将闭包参数用作完成处理程序。 该函数在开始操作后返回,但是直到操作完成才调用闭包

A已启动B后,它返回,在调用C时,调用A的调用已启动B具有已经返回。您显然在要求不可能!

那么您打算做什么?

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

在少数情况下,需要将异步性包装为同步操作,并且还有更多的情况,人们试图这样做以使异步性更易于处理,但最终却破坏了过程中异步性的所有好处。进行这种包装通常看起来很简单。但是,除非您对GCD块模型信号量线程阻塞死锁有所了解,否则它会为那些疏忽的人保留陷阱。如果您的意图太试图包装异步性,那么更好的方法是采用异步方式,在您的情况下,应弄清楚如何使闭包

C

在相应的调用之后被异步调用更长的时间来执行所需的操作您的方法A中的终止,并且不再存在。 30年前,异步是日常编程的深奥终结,今天,它已成为其核心,您需要了解和使用它。如果尝试拥抱异步之后,您确定有一种罕见的情况需要将其隐藏在同步包装中,请在SO上搜索

asynchronous

semaphore等,您应该找到解决方案。
如果您陷于

异步性

,或者实际上是在问完全不同的问题,请提出一个新问题,说明您已完成/尝试过的事情,等等,毫无疑问,有人会帮助您进行下一步。
HTH

© www.soinside.com 2019 - 2024. All rights reserved.