Reputation: 1169
In a class I'm writing to work with WeatherUnderground, I need a number of functions all nearly identical to this function, which in this form works fineonC:
func currentConditions(completion: (result: WUConditionResponse?) -> Void) -> Request {
url = urlBuilder("conditions")
let request = Alamofire.request(.GET, url)
.validate()
.responseObject { (response: Result<WUConditionResponse, NSError>) in
completion(result: response.value)
}
return request
}
Rather than write them all separately, I tried this:
private typealias AFCompletion = (result: EVObject?) -> Void
private func current(command: String, onCompletion: AFCompletion) -> Request {
let function = {(completion: AFCompletion) -> Request in
self.url = self.urlBuilder(command)
let request = Alamofire.request(.GET, self.url)
.validate()
.responseObject { (response: Result<EVObject, NSError>) in
completion(result: response.value!)
}
return request
}
return function(onCompletion)
}
Followed by
func currentConditions(completion: (result: WUConditionResponse?) -> Void) -> Request {
let myCompletion = completion as! AFCompletion
return current("conditions", onCompletion: myCompletion)
}
where WUConditionResponse
is a subclass of EVObject
. I then use the construct with the statement, unchanged from what was working:
foo.currentConditions { (conditions: WUConditionResponse?) in
print(conditions)
}
Done this way, I get an EXC_BAD_INSTRUCTION
fault on the downcast to AFCompletion. I'm at a loss to see the problem. Why does the downcast fault? Complete answers notwithstanding, how might I debug this further?
Upvotes: 1
Views: 67
Reputation: 57184
That is not possible the way you are trying to do it. The closure you pass in
foo.currentConditions { (conditions: WUConditionResponse?) in
print(conditions)
}
accepts only WUConditionResponse
, one specific subclass of EVObject
. If you cast that closure to AFCompletion
, the resulting closure has to accept every EVObject
which it does not.
What you can do is create a second only calling the completion
if the actually passed in object is of correct type rather than casting:
func currentConditions(completion: (result: WUConditionResponse?) -> Void) -> Request {
let myCompletion : AFCompletion = { res in
if res != nil || res! is WUConditionResponse {
return completion(res as! WUConditionResponse?)
}
return false // default return
}
return current("conditions", onCompletion: myCompletion)
}
Upvotes: 1