我从一个看起来像这样的函数开始:
func getUser(command: APICommand, id: Int, handler: (apiResponse: APIResponse<User>) -> Void ) {
let url = apiPath + "users/\(id)"
Alamofire.request(.GET, url, parameters: requestParameters)
.responseObject { (a:NSURLRequest, b:NSHTTPURLResponse?, c:User?, d:AnyObject?, e:NSError? ) in
let apiResponse = APIResponse(command: command,request: a, response: b, swiftObject: c, rawObject: d, error: e)
if AlamofireAPIRequestRepository.resultIsRetryableError(e, command: command) {
println("retrying request")
command.retry()
} else {
handler(apiResponse: apiResponse)
}
}
}
我将会有许多看起来非常相似的函数,例如getUserList()
。
看着这个我意识到整个Alamofire.request电话将是锅炉板代码。唯一的区别是传递给闭包的参数类型c被responseObject()
方法调用。在这种情况下,它是User?
,在getUserList()
方法中它将是UserList?
有什么方法可以让我更通用,并避免看起来只是&#34;样板&#34;码? 我这是我尝试过的。
func alamofireGetRequest<T>(url: URLStringConvertible, parameters: [String: AnyObject]?,
command: APICommand, handler: (apiResponse: APIResponse<T>) -> Void) -> Void {
Alamofire.request(.GET, url, parameters: parameters)
.responseObject { (a:NSURLRequest, b:NSHTTPURLResponse?, c:T?, d:AnyObject?, e:NSError? ) in
let apiResponse = APIResponse(command: command,request: a, response: b, swiftObject: c, rawObject: d, error: e)
if AlamofireAPIRequestRepository.resultIsRetryableError(e, command: command) {
println("retrying request")
command.retry()
} else {
handler(apiResponse: apiResponse)
}
}
}
但是编译器抱怨:
无法调用&#39; responseObject&#39;使用类型的参数列表 &#39;((NSURLRequest,NSHTTPURLResponse?,T?,AnyObject?,NSError?) - &gt; _)&#39;
如果我更换c:T?上面用c:用户?很高兴。
下面的评论引用了这个question,这可以解释为什么我尝试的解决方案不起作用,但确实回答了我想要避免这些重复代码的问题。
答案 0 :(得分:0)
我认为我找到了一个可以接受的解决方案。
下面是代码的相关部分,但基本上我最终将一个AnyObject的参数类型传递给闭包而不是泛型。在你说我在作弊之前,你必须明白我的原始电话会看起来像这样。
func testGetUserRequestSuccess() {
let getUserCommand=commandFactory.createGetUserCommandUsing(apiRepo, id: 1) {
if let swiftObject = $0.swiftObject {
XCTAssertEqual(swiftObject.id!, 1, "id is correct")
}
self.expectation.fulfill()
}
commandProcessor.processCommand(getUserCommand)
wait(5)
}
现在看起来像这样:
func testGetUserRequestSuccess() {
let getUserCommand=commandFactory.createGetUserCommandUsing(apiRepo, id: 1) {
if let swiftObject = $0.swiftObject as? User {
XCTAssertEqual(swiftObject.id!, 1, "id is correct")
}
self.expectation.fulfill()
}
commandProcessor.processCommand(getUserCommand)
wait(5)
}
所以我必须将as? User
强制转换添加到if let
语句中,这似乎是合理的。
&#34;专业&#34;代码(每个操作将重复的内容)
func getUser(retriesUse retryProcessor: APICommandProcessor, command: APICommand, id: Int, handler: (apiResponse: APIResponse) -> Void ) {
let url = apiPath + "users/\(id)"
Alamofire.request(.GET, url, parameters: requestParameters)
.responseObject { (a:NSURLRequest, b:NSHTTPURLResponse?, c:User?, d:AnyObject?, e:NSError? ) in
let apiResponse = APIResponse(command: command,request: a, response: b, swiftObject: c, rawObject: d, error: e)
self.finishResponse(command, retryProcessor: retryProcessor, apiResponse: apiResponse, handler: handler)
}
}
我想要分解的共同部分(此时主要是占位符)
func finishResponse(command: APICommand, retryProcessor: APICommandProcessor, apiResponse: APIResponse, handler: (apiResponse: APIResponse) -> Void) -> Void {
if AlamofireAPIRequestRepository.resultIsRetryableError(apiResponse.error, retryProcessor: retryProcessor, command: command) {
println("retrying \(command)")
retryProcessor.retryCommand(command)
} else {
println("request completed")
handler(apiResponse: apiResponse)
}
}
上面使用的支持结构:
struct APIResponse {
let command: APICommand
let request: NSURLRequest
let response: NSHTTPURLResponse?
let swiftObject: AnyObject?
let rawObject: AnyObject?
let error: NSError?
}