我目前正在学习Swift(4)/ iOS编程。我是OOP的新手,但是确实有函数式编程的经验。有一个概念使我有些困惑...
在课程/示例中,我遵循的功能主要是这样的:
func getUsername(forUid uid: String, handler: @escaping (_ username: String) -> Void) {
//Do stuff
handler("MyName")
}
名称是由闭包传递的,我几乎看不到像这样的函数:
func getUsername(forUid uid: String) -> String) {
//Do stuff
return "MyName"
}
是不推荐使用的第二种方法,还是该功能仍然有用。我们何时以及为什么使用第一个变体?
答案 0 :(得分:1)
我们将第一个变量用于异步编程。例如,请参见
func getUsername(forUid uid: String, handler: @escaping (_ username: String) -> Void) {
DispatchQueue.main.async {
// do some asynchronous stuff
handler("MyName")
}
}
请注意handler
必须放在async
闭包内,否则将因为async
不阻塞而立即调用该处理程序。现在,如果我们使用return
而不是handler
,则会出现编译错误,因为您的函数未返回任何值,因此要修复编译错误,它必须在函数级别(而不是在async
块)。如果它不在async
块中,它将立即返回(与上面的第二个handler
情况相同,因此,如果要执行异步任务,则必须 使用闭包。) ,如果您不使用异步内容,则可以安全地在代码中使用第二个变体。
除了异步编程外,闭包也用于同步编程中,例如,map
函数使用闭包作为参数来定义对象的映射方式。
答案 1 :(得分:0)
当然它不被弃用。 您应该对异步任务使用闭包,否则返回值。
答案 2 :(得分:0)
通过示例更容易获得它。这是我从API获得的一些地方:
func getPlaces(onSuccess: @escaping(_ places: [Place]?) -> Void, onFailure: @escaping(Error, _ title: String?, _ message: String?) -> Void) {
//perform API request...
//[...]
//...
// Session
session.dataTask(with: requestURL) { (data, response, error) in
guard error == nil else {
//handling Error
onFailure(error!, "Error", error?.localizedDescription)
group.leave()
return
}
//...
//handling succes
else {
var places: [Place] = []
places = responseJson.places!
onSuccess(places)
}
group.leave()
}.resume()
}
group.wait()
return
}
如您所见,我要处理成功和错误。这是我的用法:
APIManager.shared.getPlaces(onSuccess: { (places) in
//handling success
}
}) { (error, title, message) in
DispatchQueue.main.async {
self.present(getAlertFromError(title: title, message: message), animated: true)
}
}