Ios 如何在Swift中传递参数未知且返回值为参数的函数

Ios 如何在Swift中传递参数未知且返回值为参数的函数,ios,swift,function,parameters,swift2,Ios,Swift,Function,Parameters,Swift2,我希望传递一个函数作为参数,因为我处理的是web服务,并且我注意到代码是重复的 片段1 Service.getAllVouchersUsingCallback() { (response, data, error) -> Void in guard let statusCode = response?.statusCode else { Util.showToastWithMessage(Messages.NO_INTERNET_CONNECTION)

我希望传递一个函数作为参数,因为我处理的是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)
因此,我想知道如何传递任何函数,即,任何数量的参数或任何数量的返回值,因为在这种情况下,我只传递数据,但可能将来我需要另一种函数


提前感谢。

探索返回函数的函数是一个很大的问题。我们有一段代码:

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)
}
我们只想弄清楚在这种情况下,
success
是什么。在你的第一个例子中,它是:

{ self.loadVouchersWithData($0) }
在你的第二个例子中:

{ self.loadAndGetCategories($0, withInialText: "Category ") }
这两个函数都接受
NSData
,但不返回任何内容,就像我们想要的那样

因此,我们需要一种方法来获取第一块代码和插件,这会发生变化。我们需要一个函数,它接受一个“on success”函数并返回一个“handle all 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)
        }
    }
}
这是一个函数,它接受一个函数,该函数接受一个NSData,但不返回任何内容,整个函数返回一个函数,该函数接受一个响应、数据、错误元组,但不返回任何内容。想一想。你真的想让它深入人心,因为它真的,真的很强大

好的,希望这开始有点下沉,所以我要继续。语法非常庞大,所以Swift给了我们一个很好的技巧来简化它,称为currying:

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)
    }
}
(我知道这可能看起来不太简单,但事实上确实如此,而且它确实让函数的其余部分变得更简单。)

这(几乎)与之前的声明完全相同。在那条线上调解一会儿。注意
f(x:T)(y:U)
双括号语法。请注意,我可以在末尾将
->Void
放在何处

咖喱就像现在传递一些参数,以后再传递其余的参数

好的,那么我们如何使用它呢

Service.getAllVouchersUsingCallback(successHandler{ self.loadVouchersWithData($0) })
Service.getAllCategoriesUsingCallback(successHandler{ self.loadAndGetCategories($0, withInialText: "Category ") })
我们调用需要一个(响应、数据、错误)的东西,并用一个获取数据的函数将调用
successHandler
的结果传递给它

这将消除你所说的所有重复。这是一个特别复杂的currying版本,因为有很多级别的函数。但它也显示了这项技术的强大


您可能想暂时搁置这一点,然后返回到更简单的介绍,例如。然后,当这有意义时,回到这里。

不清楚这其中的哪一部分是重复的,因为您只给出了一个示例。你能演示一下第二个是什么样子的,它有你想要提取的重复代码吗?(那可能是除了
NSData->()
?)以外的任何东西)@RobNapier,我刚刚更新了我的问题。正如您所看到的,代码非常相似,但是当响应为200时,操作会发生变化。@RobNaiper,哇!我非常感谢你花时间回答我的问题。你的回答很清楚,很有价值。我非常感谢你们所做的一切。@RobNapier真正的史诗般的和有益的展览!我希望在我即将到来的项目中使用它。@Rob Naiper,对我有效的是
self.successHanler{self.loadVouchersWithData($0)}(response:response,whichdata:data)
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?) {
Service.getAllVouchersUsingCallback(successHandler{ self.loadVouchersWithData($0) })
Service.getAllCategoriesUsingCallback(successHandler{ self.loadAndGetCategories($0, withInialText: "Category ") })