如何在 Swift 中传递具有未知参数和返回值的函数作为参数
How to pass a function with unknown parameters and returned value as a parameter in Swift
我想将函数作为参数传递,因为我正在处理 Web 服务,并且我注意到代码是重复的。
片段 1
Service.getAllVouchersUsingCallback() { (response, data, error) -> Void in
guard let statusCode = response?.statusCode else {
Util.showToastWithMessage(Messages.NO_INTERNET_CONNECTION)
return
}
switch statusCode {
case 200:
self.loadVouchersWithData(data!)
case 503:
Util.showToastWithMessage(Messages.SERVICES_NOT_AVAILABLE)
default:
Util.showToastWithMessage(Messages.UNEXPECTED_RESPONSE)
}
}
片段 2
Service.getAllCategoriesUsingCallback { (response, data, error) -> Void in
guard let statusCode = response?.statusCode else {
Util.showToastWithMessage(Messages.NO_INTERNET_CONNECTION)
return
}
switch statusCode {
case 200:
self.loadAndGetCategories(data!, withInialText: "Category ")
case 503:
Util.showToastWithMessage(Messages.SERVICES_NOT_AVAILABLE)
default:
Util.showToastWithMessage(Messages.UNEXPECTED_RESPONSE)
}
}
重复的部分是状态代码为nil
时发生的情况,以及响应为200
时我必须执行的操作。我想函数签名应该是这样的:
func dealWithWebServiceResponse(response: NSURLResponse?, withData data: NSData?, whichActionIs action: whateverFunctionType)
所以,我想知道如何传递任何函数,即任何数量的参数或任何数量的 return 值,因为在这种情况下我只传递数据,但可能在未来我需要另一种功能。
提前致谢。
探索return函数的函数是一个很好的问题。所以我们有这段代码:
guard let statusCode = response?.statusCode else {
Util.showToastWithMessage(Messages.NO_INTERNET_CONNECTION)
return
}
switch statusCode {
case 200:
// <<================ Right here, we want to do "something different"
case 503:
Util.showToastWithMessage(Messages.SERVICES_NOT_AVAILABLE)
default:
Util.showToastWithMessage(Messages.UNEXPECTED_RESPONSE)
}
那么我们如何做 "something different?" 我们传递一个函数。该函数需要使用 "data" 因为这是我们唯一拥有的东西。您可能认为该函数采用 "other things"(类似于 "Category "),但实际上并非如此。 这个代码对"Category "一无所知。在程序的早期,必须有其他东西处理该部分。这里唯一不同的是数据。因此,让我们假装我们拥有该功能一秒钟:
let success: (NSData) -> Void = ...
...
case 200:
success(data!)
...
我们只想弄清楚success
在这种情况下是什么。那么,在您的第一个示例中,它是:
{ self.loadVouchersWithData([=12=]) }
在你的第二个例子中是:
{ self.loadAndGetCategories([=13=], withInialText: "Category ") }
这两个函数都不需要 NSData
和 return,就像我们想要的那样。
所以我们想要一种方法来获取第一个代码块并插入这个改变的东西。我们想要一个接受 "on success" 函数和 return 一个 "handle all the stuff" 函数的函数。让我们把它写下来:
func successHandler(success: (NSData) -> Void) -> (NSHTTPURLResponse?, NSData?, NSError?) -> Void {
return { (response: NSHTTPURLResponse?, data: NSData?, error: NSError?) in
guard let statusCode = response?.statusCode else {
Util.showToastWithMessage(Messages.NO_INTERNET_CONNECTION)
return
}
switch statusCode {
case 200:
success(data!) // <==== Here's the part that changes!
case 503:
Util.showToastWithMessage(Messages.SERVICES_NOT_AVAILABLE)
default:
Util.showToastWithMessage(Messages.UNEXPECTED_RESPONSE)
}
}
}
哇哦,第一行真是太棒了。一起来看看吧:
func successHandler(success: (NSData) -> Void) -> (NSHTTPURLResponse?, NSData?, NSError?) -> Void {
这是一个函数,它接受一个接受 NSData 的函数,return什么都没有,而整个函数 return 是一个接受响应、数据、错误元组和 return没什么。想一想。你真的很想让它深入人心,因为它真的非常强大。
好吧,希望这会开始一点点下沉,所以我要继续前进。语法非常庞大,所以 Swift 给了我们一个很好的技巧来简化它,称为柯里化:
func successHandler(success: (NSData) -> Void)(response: NSHTTPURLResponse?, data: NSData?, error: NSError?) {
guard let statusCode = response?.statusCode else {
Util.showToastWithMessage(Messages.NO_INTERNET_CONNECTION)
return
}
switch statusCode {
case 200:
success(data!) // <==== Here's the part that changes!
case 503:
Util.showToastWithMessage(Messages.SERVICES_NOT_AVAILABLE)
default:
Util.showToastWithMessage(Messages.UNEXPECTED_RESPONSE)
}
}
现在的声明是:
func successHandler(success: (NSData) -> Void)(response: NSHTTPURLResponse?, data: NSData?, error: NSError?) {
(我知道这可能看起来并没有简单多少,但它确实如此,而且它确实使函数的其余部分更简单。)
这与之前的声明(几乎)完全相同。在那条线上调解片刻。请注意 f(x: T)(y: U)
双括号语法。请注意我可以在最后放置 -> Void
的地方。
柯里化就像现在传递一些参数,然后可以传递其余的参数。
好的,那么我们如何使用它呢?
Service.getAllVouchersUsingCallback(successHandler{ self.loadVouchersWithData([=18=]) })
Service.getAllCategoriesUsingCallback(successHandler{ self.loadAndGetCategories([=18=], withInialText: "Category ") })
我们调用我们想要一个 (response,data,error) 的东西,并将调用 successHandler
的结果传递给它,函数接受一个数据。
这应该会删除您所说的所有重复项。这是一个特别复杂的柯里化版本,因为函数有很多层次。但这也说明了这项技术的强大。
您可能想暂时搁置一下,回到更简单的介绍,例如 Introduction to Function Currying in Swift。然后,当这有意义时,回到这个。
我想将函数作为参数传递,因为我正在处理 Web 服务,并且我注意到代码是重复的。
片段 1
Service.getAllVouchersUsingCallback() { (response, data, error) -> Void in
guard let statusCode = response?.statusCode else {
Util.showToastWithMessage(Messages.NO_INTERNET_CONNECTION)
return
}
switch statusCode {
case 200:
self.loadVouchersWithData(data!)
case 503:
Util.showToastWithMessage(Messages.SERVICES_NOT_AVAILABLE)
default:
Util.showToastWithMessage(Messages.UNEXPECTED_RESPONSE)
}
}
片段 2
Service.getAllCategoriesUsingCallback { (response, data, error) -> Void in
guard let statusCode = response?.statusCode else {
Util.showToastWithMessage(Messages.NO_INTERNET_CONNECTION)
return
}
switch statusCode {
case 200:
self.loadAndGetCategories(data!, withInialText: "Category ")
case 503:
Util.showToastWithMessage(Messages.SERVICES_NOT_AVAILABLE)
default:
Util.showToastWithMessage(Messages.UNEXPECTED_RESPONSE)
}
}
重复的部分是状态代码为nil
时发生的情况,以及响应为200
时我必须执行的操作。我想函数签名应该是这样的:
func dealWithWebServiceResponse(response: NSURLResponse?, withData data: NSData?, whichActionIs action: whateverFunctionType)
所以,我想知道如何传递任何函数,即任何数量的参数或任何数量的 return 值,因为在这种情况下我只传递数据,但可能在未来我需要另一种功能。
提前致谢。
探索return函数的函数是一个很好的问题。所以我们有这段代码:
guard let statusCode = response?.statusCode else {
Util.showToastWithMessage(Messages.NO_INTERNET_CONNECTION)
return
}
switch statusCode {
case 200:
// <<================ Right here, we want to do "something different"
case 503:
Util.showToastWithMessage(Messages.SERVICES_NOT_AVAILABLE)
default:
Util.showToastWithMessage(Messages.UNEXPECTED_RESPONSE)
}
那么我们如何做 "something different?" 我们传递一个函数。该函数需要使用 "data" 因为这是我们唯一拥有的东西。您可能认为该函数采用 "other things"(类似于 "Category "),但实际上并非如此。 这个代码对"Category "一无所知。在程序的早期,必须有其他东西处理该部分。这里唯一不同的是数据。因此,让我们假装我们拥有该功能一秒钟:
let success: (NSData) -> Void = ...
...
case 200:
success(data!)
...
我们只想弄清楚success
在这种情况下是什么。那么,在您的第一个示例中,它是:
{ self.loadVouchersWithData([=12=]) }
在你的第二个例子中是:
{ self.loadAndGetCategories([=13=], withInialText: "Category ") }
这两个函数都不需要 NSData
和 return,就像我们想要的那样。
所以我们想要一种方法来获取第一个代码块并插入这个改变的东西。我们想要一个接受 "on success" 函数和 return 一个 "handle all the stuff" 函数的函数。让我们把它写下来:
func successHandler(success: (NSData) -> Void) -> (NSHTTPURLResponse?, NSData?, NSError?) -> Void {
return { (response: NSHTTPURLResponse?, data: NSData?, error: NSError?) in
guard let statusCode = response?.statusCode else {
Util.showToastWithMessage(Messages.NO_INTERNET_CONNECTION)
return
}
switch statusCode {
case 200:
success(data!) // <==== Here's the part that changes!
case 503:
Util.showToastWithMessage(Messages.SERVICES_NOT_AVAILABLE)
default:
Util.showToastWithMessage(Messages.UNEXPECTED_RESPONSE)
}
}
}
哇哦,第一行真是太棒了。一起来看看吧:
func successHandler(success: (NSData) -> Void) -> (NSHTTPURLResponse?, NSData?, NSError?) -> Void {
这是一个函数,它接受一个接受 NSData 的函数,return什么都没有,而整个函数 return 是一个接受响应、数据、错误元组和 return没什么。想一想。你真的很想让它深入人心,因为它真的非常强大。
好吧,希望这会开始一点点下沉,所以我要继续前进。语法非常庞大,所以 Swift 给了我们一个很好的技巧来简化它,称为柯里化:
func successHandler(success: (NSData) -> Void)(response: NSHTTPURLResponse?, data: NSData?, error: NSError?) {
guard let statusCode = response?.statusCode else {
Util.showToastWithMessage(Messages.NO_INTERNET_CONNECTION)
return
}
switch statusCode {
case 200:
success(data!) // <==== Here's the part that changes!
case 503:
Util.showToastWithMessage(Messages.SERVICES_NOT_AVAILABLE)
default:
Util.showToastWithMessage(Messages.UNEXPECTED_RESPONSE)
}
}
现在的声明是:
func successHandler(success: (NSData) -> Void)(response: NSHTTPURLResponse?, data: NSData?, error: NSError?) {
(我知道这可能看起来并没有简单多少,但它确实如此,而且它确实使函数的其余部分更简单。)
这与之前的声明(几乎)完全相同。在那条线上调解片刻。请注意 f(x: T)(y: U)
双括号语法。请注意我可以在最后放置 -> Void
的地方。
柯里化就像现在传递一些参数,然后可以传递其余的参数。
好的,那么我们如何使用它呢?
Service.getAllVouchersUsingCallback(successHandler{ self.loadVouchersWithData([=18=]) })
Service.getAllCategoriesUsingCallback(successHandler{ self.loadAndGetCategories([=18=], withInialText: "Category ") })
我们调用我们想要一个 (response,data,error) 的东西,并将调用 successHandler
的结果传递给它,函数接受一个数据。
这应该会删除您所说的所有重复项。这是一个特别复杂的柯里化版本,因为函数有很多层次。但这也说明了这项技术的强大。
您可能想暂时搁置一下,回到更简单的介绍,例如 Introduction to Function Currying in Swift。然后,当这有意义时,回到这个。