我正在构建一个简单的主题引擎,并希望有一个扩展添加UISwipeGestureRecognizer
到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
指令公开。是否可以将此行为添加到我的扩展中?
更新:Theme
是Swift枚举,所以我不能在Themeable
协议前面添加@objc
4条答案
按热度按时间uinbv5nw1#
我所能想到的最简洁的解决方案是使用所讨论的方法在
UIViewController
上定义一个私有扩展。通过将作用域限制为private
,对该方法的访问被隔离到定义该协议的源文件中。tjvv9vkg2#
我找到了一个解决方案。可能不是完美的一个,但它的工作。因为我不能定义
Themeable
协议为@objc
,因为它使用的是Swift唯一的enum
,我决定移动方法,我想调用的“父”协议,并定义这个协议为@objc
。它似乎工作,但我真的不喜欢它说实话...iih3973s3#
您是否考虑过创建一个 Package 器,以便从一个@objc函数调用非@objc函数?
kcrjzv8t4#
这里有一个类似的用例,你可以通过选择器调用一个方法,而不用像swift中那样使用dynamic关键字来调用@objc。这样做,你就指示编译器隐式地使用动态调度。