Swift中的NSMethodSignature怎麼了?

發表於2014-12-17

讓Cocoa框架支援Swift語言的工作,給了我們一個全新的機會來審視裡面的眾多API。我們發現大多數不適合Swift編碼風格的類,基本都是優先考慮安全性的。比如,一些關係到動態方法呼叫的類在Swift中沒有暴露出來,它們NSInvocationNSMethodSignature這兩個類。

我們最近收到一個bug報告,是從一個注意到這個現象的開發者發來的。他曾經使用Objective-C中的NSMethodSignature來在執行時檢查方法引數的型別,但在遷移到Swift的過程中發現NSMethodSignature方法失效了。實際分析一下,被遷移的程式碼能夠接收不同簽名的HTTP處理程式,比如:

在Objective-C裡,NSMethodSignature能被用來檢測API引數型別,第一個方法的API必須接收一個[String: String]型別的引數,第二個方法需要接收一個JSON型別。然而,Swift足夠強大,能夠簡單的處理這種狀況而無需動用NSMethodSignature,並且在某種程度上,還能降低對編譯器提供的型別提示和記憶體安全的破壞。

下面是在Swift用另一種方法來解決這個問題的程式碼:

首先,我們使用協議來定義一個介面,任何想要處理我們的HTTPRequest的程式都必須通過這個藉口。這個協議非常簡單,裡面只包含一種方法。

這裡為什麼使用協議而不是HTTPHandler的子類呢?因為協議更靈活,能夠將實現的細節交給客戶端去做。如果使用HTTPHandler子類,我們需要讓客戶端同樣使用它,並且強制客戶端使用相同的引用型別。然而使用協議的話,客戶端能夠自行決定在程式碼中使用適合的型別,無論它們是類、結構體甚至是列舉型別。

然後,我們的HTTPServer類擁有一個泛型方法,它接收一個HTTPHandlerType型別作為引數。使用處理程式的關聯型別,它能執行args引數的條件式向下轉換(conditional downcast),來檢測這個處理程式是否應該處理該http請求。現在我們能看到定義HTTPHandlerType作為協議的好處了,HTTPServer不需要知道處理程式如何響應請求,甚至不需要知道處理程式本身,它只需要知道能夠處理請求的值。

當我們的HTTPServer接收一個請求時,它將遍歷一遍裡面的處理程式,看是否有程式能響應這個請求。

現在我們能很簡單的建立一個自定義的包含不同的引數型別的HTTPHandlerType,並且將它註冊到HTTPServer

通過協議和泛型的結合,現在我們能優雅的編寫Swift程式碼來建立和註冊包含不同型別的HTTP處理程式。這個方法還能夠讓編譯器在保證執行時效能的同時確保型別安全。

相關文章