从协议扩展中调用选择器 [英] Calling selector from protocol extension
问题描述
我正在构建简单的主题引擎,并希望有一个扩展,它将UISwipeGestureRecognizer
添加到UIViewController
I'm building simple theme engine and would like have an extension which adds UISwipeGestureRecognizer
to UIViewController
这是我的代码:
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)
}
}
当然编译器找不到#selector(Self.switchCurrentTheme)
,因为它不是通过@objc
指令公开的.是否可以将此行为添加到我的扩展程序中?
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?
更新:Theme
是Swift枚举,所以我不能在Themeable
协议之前添加@objc
UPDATE: Theme
is a Swift enum, so I can't add @objc
in front of Themeable
protocol
推荐答案
我能想到的最干净,可行的解决方案是使用所讨论的方法在UIViewController
上定义一个私有扩展.通过将范围限制为private
,可以仅在定义协议的源文件中访问此方法.其外观如下:
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 to private
, access to this method is isolated to within the source file where the protocol is defined in. Here's what it looks like:
protocol Themeable {
func themeDidUpdate(currentTheme: Theme) -> Void
}
fileprivate extension UIViewController {
@objc func switchCurrentTheme() {
guard let themeableSelf = self as? Themeable else {
return
}
Theme.switchTheme()
themeableSelf.themeDidUpdate(Theme.currentTheme)
}
}
extension Themeable where Self: UIViewController {
func addSwitchThemeGestureRecognizer() {
let gestureRecognizer = UISwipeGestureRecognizer(target: self, action:#selector(switchCurrentTheme))
gestureRecognizer.direction = .Down
gestureRecognizer.numberOfTouchesRequired = 2
self.view.addGestureRecognizer(gestureRecognizer)
}
}
这篇关于从协议扩展中调用选择器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!