Translate Optional Delegate Protocol Methods to Swift Block-based Event Handlers Using Nested Objects
Found this little gem in a library called NextGrowingTextView
, shortened to make the point clear with less code. It’s a collection of block-based event handlers in a little class:
public class Delegates {
public var textViewDidBeginEditing: (NextGrowingTextView) -> Void
public var textViewDidEndEditing: (NextGrowingTextView) -> Void
public var textViewDidChange: (NextGrowingTextView) -> Void
public var willChangeHeight: (CGFloat) -> Void
public var didChangeHeight: (CGFloat) -> Void
}
Update 2023-12-20: Re-reading this today, I notice I never mentioned that I’d rather use a struct
; there’s no benefit of using a reference type object if all it does is own the closures. public struct Delegates
it is, then! By the way, they removed the Delegates
type in the meantime, starting with a deprecation in 2017.
So there’s a bunch of traditional delegate callbacks – only they are not defined as protocol requirements but as properties of an otherwise state-less type.
You use it like this:
let growingTextView: NextGrowingTextView
growingTextView.delegates.textViewDidChange = { (growingTextView: NextGrowingTextView) in
// Do something
}
Many views I write have less than 5 event callbacks. But if you write a complex component with many interactions or lots of decision-making, then it might be a good idea to wrap these up in a Delegates
sub-type:
class BananaComponent: UIView {
// ...
let delegates = Delegates()
class Delegates {
// Favor "no-op" defaults over optionals
var bananaComponentDidShow: (BananaComponent) -> Void = { _ in }
}
}