這是探索返回函數的函數的一個很大的問題。所以我們有這樣的代碼塊:
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)
}
那麼我們該怎麼做「有點不同?」我們傳遞一個函數。該功能需要採取「數據」,因爲這是我們唯一的。你可能會認爲這個函數需要「其他的東西」(比如「Category」),但它確實沒有。 這個的代碼並不知道任何關於「Category」的信息。在項目的早些時候,其他的東西必須處理那部分。唯一不同的是數據。因此,讓我們假設我們有一個功能第二:
let success: (NSData) -> Void = ...
...
case 200:
success(data!)
...
我們只是想弄清楚success
在這種情況下。那麼,在你的第一個例子,它是:
{ self.loadVouchersWithData($0) }
,並在你的第二個例子是:
{ self.loadAndGetCategories($0, withInialText: "Category ") }
這些都是採取NSData
不返回任何兩種功能,就像我們想要的。
所以我們想要一種方法來取代第一塊代碼和插件這個變化的東西。我們需要一個函數,它需要一個「成功」函數並返回一個「處理所有東西」函數。讓我們一起寫出來:
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返回任何結果,而整個函數返回一個函數,它的響應,數據,錯誤元組,並且沒有返回。冥想一會兒。你真的想讓它沉浸其中,因爲它真的很強大。好吧,希望這開始有點沉淪,所以我要繼續前進。語法是非常巨大的,所以雨燕給了我們一個很好的技巧來簡化它,叫柯里:
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?) {
(我知道這可能似乎並不簡單得多,但確實如此,並且它確實使功能的其餘部分更簡單。)
這是(幾乎)與前面的聲明完全相同。暫時斡旋那條線。請注意0雙圓括號語法。請注意我最後可以放棄-> Void
。
柯里格就像現在傳遞一些參數,並能夠在稍後通過其他參數。
好的,那我們怎麼用呢?
Service.getAllVouchersUsingCallback(successHandler{ self.loadVouchersWithData($0) })
Service.getAllCategoriesUsingCallback(successHandler{ self.loadAndGetCategories($0, withInialText: "Category ") })
我們把我們的東西,想要一個(響應,數據錯誤),並通過它調用successHandler
與需要數據的函數的結果。
而且應該刪除所有你正在談論的重複。這是一個特別複雜的版本,因爲有很多級別的功能。但它也表明了這種技術的強大。
您可能需要暫時擱置一會兒,然後回到較簡單的介紹,例如Introduction to Function Currying in Swift。那麼,當這是有道理的,回到這個。
目前還不清楚這是重複的哪一部分,因爲你只給出了一個例子。你能證明第二個會看起來像是有重複的代碼嗎? (這可能是除了'NSData - >()'以外的任何東西?) –
@RobNapier,我剛剛更新了我的問題。正如你所看到的代碼非常相似,但是當響應變化爲200時的動作。 – lmiguelvargasf