Swift:逃逸闭包捕获了非逃逸参数'onCompletion'。

23

我的swift有问题。我正在尝试发送API请求,然后检索数据,但是我收到以下错误消息:

"Swift: Escaping closure captures non-escaping parameter 'onCompletion'".

有人知道我怎么才能解决这个问题吗?谢谢提前

代码:


class RestApiManager: NSObject {
    static let sharedInstance = RestApiManager()
    
    let baseURL = "http://api.randomuser.me/"
    
    func getRandomUser(onCompletion : (JSON) -> Void) {
        makeHTTPGetRequest(path: baseURL, onCompletion: { json, err -> Void in
            onCompletion(json)
        })
    }
    
    func makeHTTPGetRequest(path: String, onCompletion: ServiceResponse) {
        let request = NSMutableURLRequest(url : URL(string: path)! as URL)
        
        let session = URLSession.shared
        
        let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
            let json:JSON = JSON(data as Any)
            onCompletion(json, error as NSError?)
        })
        task.resume()
    
    }
}

2
请查看此链接:https://dev59.com/a1YO5IYBdhLWcg3wKOjt#46245943;逃逸闭包:逃逸闭包是指在传递给函数的闭包在该函数返回后被调用。换句话说,它的生命周期超出了传递给它的函数。 非逃逸闭包:在传递给函数的闭包在函数返回之前被调用,即在函数内部调用。 - wzso
4个回答

42

你需要在两个完成处理程序中使用@escaping修饰符。通常编译器会提供解决方案。

class RestApiManager: NSObject {
    static let sharedInstance = RestApiManager()

    let baseURL = "http://api.randomuser.me/"

    func getRandomUser(onCompletion : @escaping (JSON) -> Void) {
        makeHTTPGetRequest(path: baseURL, onCompletion: { json, err -> Void in
            onCompletion(json)
        })
    }

    func makeHTTPGetRequest(path: String, onCompletion: @escaping ServiceResponse) {
        let request = NSMutableURLRequest(url : URL(string: path)! as URL)

        let session = URLSession.shared

        let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
            let json:JSON = JSON(data as Any)
            onCompletion(json, error as NSError?)
        })
        task.resume()

    }
}

9

回答中提到了在完成处理程序参数声明之前添加@escaping,虽然解释简短。

以下是我从Swift文档中获取的完整信息:

逃逸闭包

当闭包作为参数传递给函数,但在函数返回后调用时,闭包被认为是逃逸函数。当您声明一个函数,其中一个参数是闭包时,您可以在参数类型之前写@escaping,以指示允许该闭包逃逸。

因此,基本上,如果要在方法返回调用完成处理程序,则在swift中将其定义为escaping,并应声明为这样:

func makeHTTPGetRequest(path: String, onCompletion: @escaping ServiceResponse)

3

这是由于您的参数 onCompletion 导致的。默认情况下,它是 @nonesacping,您需要将其标记为 @esacping,以便可以在 completionHandler 闭包中工作。

func makeHTTPGetRequest(path: String, onCompletion: @escaping ServiceResponse)

2
请使用以下内容:
class RestApiManager: NSObject {
static let sharedInstance = RestApiManager()

let baseURL = "http://api.randomuser.me/"

func getRandomUser(onCompletion : @escaping (JSON) -> Void) {
    makeHTTPGetRequest(path: baseURL, onCompletion: { json, err -> Void in
        onCompletion(json)
    })
}

func makeHTTPGetRequest(path: String, onCompletion: @escaping ServiceResponse) {
    let request = NSMutableURLRequest(url : URL(string: path)! as URL)

    let session = URLSession.shared

    let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
        let json:JSON = JSON(data as Any)
        onCompletion(json, error as NSError?)
    })
    task.resume()

}
}

请考虑突出显示您更改的代码部分,以便其他人不必阅读和比较此帖子中的代码和原始代码。 - David Rector

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接