wan*_*der 2 generics closures swift
我有一个方法,有一个名为的方法performRequest().它需要一个JSONRequest参数.JSONRequest看起来像这样:
public typealias JSONCompletionHandler = ([Entity]?, NSError?) -> Void
public class JSONRequest: Request {
public var completionHandler: JSONCompletionHandler
public var endPoint: String
}
Run Code Online (Sandbox Code Playgroud)
而且performRequest()看起来是这样的:
public func performJSONRequest<T where T: Entity>(jsonRequest: JSONRequest, _: Type) {
// Make a request which returns a data object
var entities = self.convertJSONData(data, jsonKey: jsonRequest.jsonKey, T.self)
// Error: 'T' is not identical to 'Entity'
jsonRequest.completionHandler(entities, error)
}
Run Code Online (Sandbox Code Playgroud)
如您所见,它调用convertJSONData()如下所示:
func convertJSONData<T where T: Entity>(jsonData: AnyObject, _: T.Type) -> [T] {
// Convert the data into Swift collection classes, enumerate over them, and create model objects
var json = JSON(data: jsonData as NSData, options: nil, error: nil)
var entities = [T]()
for obj in json {
let book = T(json: obj)
entities.append(book)
}
return entities
Run Code Online (Sandbox Code Playgroud)
实体是一个协议,我的所有模型类,例如Author和Book,符合.
它定义了一种方法:init(json: JSON).既然T定义为T:Entity,我可以调用T:(json: obj)创建符合的任何类的实例Entity.
我希望能够用于performJSONRequest()执行符合实体的任何对象的请求.例如,我想构建一个像这样的Book实例的请求:
var request = JSONRequest(endPoint: "books") { (let object: [Entity]?, let error: NSError?) -> Void in
// Cast object to [Book] and have fun
}
performJSONRequest<Book>(request)
Run Code Online (Sandbox Code Playgroud)
我不能为我的生活找到我将如何实现这一点.现在,我在performJSONRequest()方法中说错了'T' is not identical to 'Entity'.如果我在完成处理程序中定义数组,因为[AnyObject]我得到相同的错误:'T' is not identical to 'AnyObject'.
谢谢你的帮助!
Nat*_*ook 14
解决方案是将泛型类型移动到JSONRequest类中 - 这种方式JSONCompletionHandler可以使用您请求的泛型类型而不仅仅是Entity协议来定义.(你的一些代码似乎有点伪 - 所以这可能需要一些调整才能适应你的实现.)
JSONRequest现在是一个具有Entity类型约束的泛型类:
public class JSONRequest<T: Entity>: Request {
// completion handler defined in terms of `T`
public typealias JSONCompletionHandler = ([T]?, NSError?) -> Void
// no further changes
public var completionHandler: JSONCompletionHandler
public var endPoint: String
public init(endPoint: String, completionHandler: JSONCompletionHandler) {
self.endPoint = endPoint
self.completionHandler = completionHandler
}
}
Run Code Online (Sandbox Code Playgroud)
performJSONRequest不再需要作为单独参数传递的类型.由于jsonRequest是专门的,它从该参数获取类型信息:
public func performJSONRequest<T: Entity>(jsonRequest: JSONRequest<T>) {
// create array of `T` somehow
var entities: [T] = []
var error: NSError?
// completionHandler expects [T]? and NSError?
jsonRequest.completionHandler(entities, error)
}
Run Code Online (Sandbox Code Playgroud)
在创建JSONRequest实例时,完成处理程序中给出的类型(例如[Book]?)将设置泛型的类型JSONRequest,并在整个过程中保持:
var request = JSONRequest(endPoint: "books") { (books: [Book]?, error) in
println(books?.count)
}
performJSONRequest(request)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4207 次 |
| 最近记录: |