Reputation: 1002
There are two functions as shown below. Most of the functionality is the same in both. Its idea is to get the output of the webservice from getResponse() [Helper Callback], parse and pass the info to wrapper call back through getResult().
static func getAllDealers(dealerSearchServiceDomain: ARSDealerSearchServiceDomain, wrapperCallback:(getResult: () throws -> Void) -> Void) throws
{
try ARSInputValidator.validateZipCode(dealerSearchServiceDomain.zip)
try ARSDealerConnection.getAllDealers(dealerSearchServiceDomain, helperCallback: { (getResponse) -> Void in
do
{
let result = try getResponse()
try ARSDealerParser.parseDealerSearchResponse(dealerSearchServiceDomain)
wrapperCallback(getResult: { return })
}
catch
{
wrapperCallback(getResult: { throw error })
}
})
}
static func getDealerDetails(dealerDetailsServiceDomain: ARSDealerDetailsServiceDomain, wrapperCallback:(getResult: () throws -> Void) -> Void) throws
{
try ARSDealerConnection.getDealerDetails(dealerDetailsServiceDomain, helperCallback: { (getResponse) -> Void in
do
{
let result = try getResponse()
try ARSDealerParser.parseDealerDetailsResponse(dealerDetailsServiceDomain)
wrapperCallback(getResult: { return })
}
catch
{
wrapperCallback(getResult: { throw error })
}
})
}
I am trying to add a separate function for the common functionality like,
static func parser(serviceCallDomain: ARSServiceCallDomain ,wrapperCallback:(getResult:() throws -> String) -> Void, helperCallback:(getResponse:() throws -> String) -> Void) throws
{
helperCallback { (getResponse) -> Void in
But there is a compilation error & i am not able to complete it. There are 15+ web service calls, so a common shown as i am trying will be very helpful.
Next step, i also need to pass the functions parseDealerSearchResponse() & parseDealerDetailsResponse() to the common function.
I am new to closures. Kindly help.
//EDIT -- ADDING SAMPLE
I have a sample for the problem in Git - Refer class Layer1.swift https://github.com/vivinjeganathan/ErrorHandling/tree/Closures-Refactor
Upvotes: 0
Views: 77
Reputation: 3757
I think the best you can do to refactor the code is to define a function that handles some of the common functionality like parsing and validation and that ultimately calls the completion closure back to the controller, something like this:
static func handleResponse(parser: Parser, validator: Validator, getResult: () throws -> AnyObject, completion: (getParsedResult: () throws -> AnyObject) -> Void) {
do
{
let result = try getResult()
let parsedObject = try parser.parse(result)
try validator.validate(parsedObject)
completion(getParsedResult: { return parsedObject })
}
catch
{
completion(getParsedResult: { throw error })
}
}
notice that it receives the parser, validator, the closure that captures the result from the layer below and the completion closure that belongs to the final user (usually the View Controller), and then this function could be used like this:
static func getAllDealers(dealerSearchServiceDomain: AnyObject, wrapperCallback:(getResult: () throws -> AnyObject) -> Void) throws {
let validator = DealersValidator() // create real validator
let parser = DealersParser() // create real parser
try validator.validate(dealerSearchServiceDomain)
try ARSDealerConnection.getAllDealers(dealerSearchServiceDomain, helperCallback: { (getResponse) -> Void in
self.handleResponse(parser, validator: validator, getResult: getResponse, completion: wrapperCallback)
})
}
in this case handleResponse
lives in the same class with getAllDealers
but it can actually be a global function that every service can call.
I think that it might be possible to write a better implementation using generics but it wouldn't be much shorter than this, in the end you can't save yourself from creating the validators and parsers and call the next layer.
Upvotes: 1