Tugulab Blog.

Introducing Swift Action Delegate pattern Part 2

Here you find the Part 1 of this article.
author avatar

clacla

Here you find the Part 1 of this article.

A while ago I wrote an article which introduced what I called Swift Action Delegate pattern. It is an attempt to write less boilerplate code while implementing delegation for objects communication.

This was the core (maybe re-read the original article for more context):

protocol DelegateAction {}
protocol ActionDelegate: class {
  func actionSender(_ sender: Any, didReceiveAction action: DelegateAction)
}

Few ex-collegues gave me an interesting piece of feedback. The sender is Any type. This is a code smell and not following the Swift principles. We should send an actual type instead, avoiding casting.

Yesterday, I finally figured out how to solve this problem:

protocol DelegateAction {}
protocol ActionDelegate: class {
  func actionSender(didReceiveAction action: DelegateAction)
}

We just remove the sender from the function and pass it as part of the DelegateAction payload. If DelegateAction is an enum (as I generally suggest) it can simply be another parameter of its cases.

final class RedViewController: UIViewController {

  enum Action: DelegateAction {
    case close(sender: RedViewController)
    case complete(sender: RedViewController, success: Bool)
  }

  weak var delegate: ActionDelegate?

  func pressButton(sender: Any) {
    delegate?.actionSender(didReceiveAction: Action.close(sender: self))
  }
}

And the class which conforms to the ActionDelegate protocol, has access to the sender which is of the actual type, not a simple Any type.

final class ParentViewController: UIViewController, ActionDelegate {

  func actionSender(didReceiveAction action: DelegateAction) {
    switch action {
      case RedViewController.Action.close(let sender):
       print("Close red. Sender: \(sender)")
      case RedViewController.Action.complete(let sender, let success):
        print("Complete red. Sender: \(sender). Success: \(success)")
      default:
       print(action)
    }
  }

}

I think this makes the ActionDelegate pattern stronger than it used to be.

As always, I am curious to get your opinion and feedback.