Selectors With Pure Swift
When reading Andy’s great post on how to sugar coat the awful syntax of selectors in Swift I figured there must be a way to get rid of selectors altogether and go with Pure Swift.
Objective-C archaisms were a big letdown for me, when I started learning Swift. Well, no more!
😖#selector(tapped(_:))😖
Yuuck! Everything about it is ugly: #selector(tapped(_:))
, @objc
…
Aaah… This looks much better, doesn’t it ? It’s almost like we can forget about the dinosaurs of the past. Can we achieve that easily though? Well, let’s try.
Nothing too fancy. Just a wrapper to hide all the ugliness and forget about it forever. Is that all ? Well, let’s try and use it.
Nope 😢 The text doesn’t get printed - the selector doesn’t get called.
- Target objects in UIKit are kept as weak references to avoid reference cycles
The object that contains our closure gets released when when the function is executed.
Sure, we can keep a reference to each ClosureSelector
object, but let’s just agree to not do that.
There must be some magic way…
Obj-C runtime to the rescue!
Let’s use object association and extensions to keep the reference to the wrapper, while the button is alive.
Doesn’t look as bad as I thought it would. Besides, you write it once for each class (yes NSTimer
, you’re next!) and forget about it.
It’ll keep the ClosureSelector
object alive as long as the UIButton
is alive - object association works very similarily to properties in Objective-C, hence the OBJC_ASSOCIATION_RETAIN_NONATOMIC
flag.
On a different note, it’s strange that objc_setAssociatedObject
works with pure Swift classes, huh ?
Done! That sure looks pretty to me 🦄 I like it and I’m sure going to use it in my Swift code.
I hope that UIKit gets translated to pure swift one day, and we won’t have to resolve to such drastic measures.