Suneel G Suneel G - 7 months ago 7
Swift Question

iOS: Return a value from a function after network operation

I have to return an array after network operation in a MLPAutoCompleteTextField delegate method. Any suggestions related to this is highly helpful.

func autoCompleteTextField(textField: MLPAutoCompleteTextField!, possibleCompletionsForString string: String!, completionHandler handler: (([AnyObject]!) -> Void)!) {
//Perform network operation. Success and Failure conditions are handled below by implementing the protocol
service.getData(string)

//Have to return this only after network operation is completed either success or failure
handler(autoCompleteSuggestionsArray)
}

//Handle successful network call
func handleSuccess(model: Model) {
autoCompleteSuggestionsArray.removeAll()
for item in model.items {
if let itemName = item.name {
autoCompleteSuggestionsArray.append(itemName)
}
}
}

//Handle failed network call
//
func handleErrorWithMessage(message: String) {
autoCompleteSuggestionsArray.removeAll()
}

Answer

Having delegate methods for success and failure instead of callback closures is not a great approach for the reason shown in your example: you can't include the arguments from the scope of your autoCompleteTextField method in the delegate methods. If you are able to change your service implementation to take closures instead of using a delegate, e.g. service.getData(string:String, success:SuccessClosure, failure:FailureClosure), that would be a better situation overall.

If you aren't able to make that change, then you have to do something unfortunate, like this:

var autocompleteHandler:([AnyObject]->())? //Create a new property on your class to hold an optional reference to the handler that is visible to multiple methods

func autoCompleteTextField(textField: MLPAutoCompleteTextField!, possibleCompletionsForString string: String!, completionHandler handler: (([AnyObject]!) -> Void)!) {
    //Save reference to handler in scope that is also visible to delegate methods
    autocompleteHandler = handler

    //Perform network operation. Success and Failure conditions are handled below by implementing the protocol
    service.getData(string)
}

//Handle successful network call 
func handleSuccess(model: Model) {
    autoCompleteSuggestionsArray.removeAll()
    for item in model.items {
        if let itemName = item.name {
        autoCompleteSuggestionsArray.append(itemName)
        }
    }
    // Now that we have a result from the service, pass it to the saved handler if it is not nil
    autocompleteHandler?(autocompleteSuggestionsArray)
}

//Handle failed network call
func handleErrorWithMessage(message: String) {
    autoCompleteSuggestionsArray.removeAll()
    // Now that we have a result from the service, pass it to the saved handler if it not nil
    autocompleteHandler?(autocompleteSuggestionsArray)
}
Comments