Warpzit Warpzit - 1 month ago 9
Swift Question

When to use delegate, inout or completion in Swift?

When we call some code and need a response with multiple parameters we have multiple options in Swift:

  • Completion block

  • Delegate

  • Inout parameters

  • Wrapper object (simply put all parameters inside an object)

I was wondering if there were some good guidelines to when to use what? Specifically when would it be a bad practise to use inout instead of delegate?

To be VERY specific:
Also an example that can be used to explain:
I have class A that communicates with class B. Class A needs a list of data AND an optional error.

So right now I'm leaning towards using inouts:
Class A:

var error = ServiceError()
let wordSuggestions = B.parseSuggestionResponse(json: result as! NSDictionary, error: &error)

if error.type == .none {
// Success, now use wordSuggestions for something!
} else {
self.handleError(error: error)

Is there some disadvantages for this approach vs using delegates?


I will explain when each method should be used.

A completion block is used when the operation takes time. For example, UIView.animate has a completion block parameter because animating views take time.

A delegate is used only when some of object is present especially when that object can have multiple states. This is widely used for communication between the view and the controller When there is only a method, delegates don't work. For example, a GADInterstitial has a delegate because it can have different states, such as the user dismissing the ad, user clicks the ad and leaves the app, the ad is loaded etc.

Inout parameters are mainly used for passing value types as references. I can't find any usage of this in the iOS SDK because there is no inout in Objective-C. The closest thing to it is UnsafeMutablePointer<T>. Basically, if you want to make a method that takes a bunch of value type arguments and you want to change their value, use inout! Refer to this page for more info.

From my own experience, wrapper objects are rarely used in swift. That is because we have tuples! You can wrap everything in a tuple and pass that around. I don't usually create a new struct or class just to wrap a few parameters. But do use them if your data structure becomes something complicated like [(String, [String: (String, Int)])].