转载

Swift Generics 参数 T 限定为 Class 的一点记录

今天看以前写的网络请求的方法如下:

static func listItemWithRefIndex(refIndex: Int, orientation: String, direction: Int,     nitems: Int, response: (items: [Item]) -> Void) {     var param = [String: AnyObject]()     param["ref_index"] = refIndex     param["orientation"] = orientation     param["direction"] = direction     param["nitems"] = items     Alamofire.request(Router.ReadList(param)).responseCollection {        (_, _, result: Result<[Item]>) -> Void in         if let value = result.value {             response(items: value)         }     } } 

越看越不爽,如果下次增加方法,请求类型变成了 Student:

static func listItemWithRefIndex(refIndex: Int, orientation: String,       direction: Int, nitems: Int, response: (items: [Student]) -> Void) {         var param = [String: AnyObject]()         // 参数拼接略         // ....         Alamofire.request(Router.ReadList(param)).respon seCollection {            (_, _, result: Result<[Student]>) -> Void in             if let value = result.value {                 response(items: value)             }         }     } 

后面那段关于 Alamofire 的代码重复写了很多次。然后就想再抽一个方法,这个方法的参数有:

  1. 遵循 URLRequestConvertible 协议的类型,如上面的 Router
  2. response 里面Closures中参数的类型,如上面的 Item 和 Student
  3. 最后就是 response 了

问题在于 response 的 Closures中的参数,怎么声明。

  1. 首先它要是个 Class,问题转变为要遵循 AnyObject 协议,因为所有 class 都隐式现实了这个协议
  2. 然后他要遵循 ResponseCollectionSerializable 协议
    最后在 way 的提醒下,写成这样:
static func sendRequestWithRouter<T: protocol<AnyObject, ResponseCollectionSerializable>>(router: Router,       classType: T.Type, completionHandler: (items: [T]) -> ()) {           Alamofire.request(router).responseCollection {            (_, _, result: Result<[T]>) -> Void in             if let value = result.value {                 completionHandler(items: value)             }         }     } 

&lt;T: protocol&lt;AnyObject, ResponseCollectionSerializable&gt;

  1. AnyObject 声明了 T 是一个 Class,为什么要是 Class,要调用 T.Type
  2. T: ResponseCollectionSerializable,声明了 T 要遵循ResponseCollectionSerializable 协议

classTpye: T.Type 中的 T.Type 表示存储 T 这个类型的本身,而 T.self 表示取出其类型,这样就达到我的目的了,最后变成这样:

static func listItemWithRefIndex(refIndex: Int, orientation: String,       direction: Int, nitems: Int, response: (items: [Item]) -> Void) {         var param = [String: AnyObject]()         param["ref_index"] = refIndex         param["orientation"] = orientation         param["direction"] = direction         param["nitems"] = nitems         sendRequestWithRouter(Router.ReadList(param), classType: Item.self, completionHandler: response) } 
正文到此结束
Loading...