I'm building simple theme engine and would like have an extension which adds UISwipeGestureRecognizer
to UIViewController
Here is my code:
protocol Themeable {
func themeDidUpdate(currentTheme: Theme) -> Void
}
extension Themeable where Self: UIViewController {
func switchCurrentTheme() {
Theme.switchTheme()
themeDidUpdate(Theme.currentTheme)
}
func addSwitchThemeGestureRecognizer() {
let gestureRecognizer = UISwipeGestureRecognizer(target: self, action:#selector(Self.switchCurrentTheme))
gestureRecognizer.direction = .Down
gestureRecognizer.numberOfTouchesRequired = 2
self.view.addGestureRecognizer(gestureRecognizer)
}
}
Of course compiler can't find #selector(Self.switchCurrentTheme)
as it isn't exposed via @objc
directive. Is it possible to add this behaviour to my extension?
UPDATE: Theme
is a Swift enum, so I can't add @objc
in front of Themeable
protocol
I'm not sure but you can access it like
or you can refer this link to try Visit How to use #selector(myMethodName) in a protocol extension?
Have you considered creating a wrapper to let you call your non-@objc function from an @objc one?
The cleanest, working solution I could come up with was to define a private extension on
UIViewController
with the method in question. By limiting the scope toprivate
, access to this method is isolated to within the source file where the protocol is defined in. Here's what it looks like:I found a solution. May be not the perfect one, but it works. As I can't define
Themeable
protocol as@objc
because it uses Swift-onlyenum
I decided to move method I want to call to "parent" protocol and define this protocol as@objc
. It seems like it works but I don't really like it to be honest...