ios – 从协议扩展中调用选择器

我正在构建简单的主题引擎,并希望有一个扩展,将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指令公开.是否可以将此行为添加到我的扩展程序?

更新:主题是一个Swift枚举,所以我不能在Themeable协议前添加@objc

解决方法

我能想到的最干净,最有效的解决方案是使用相关方法在UIViewController上定义一个私有扩展.通过将范围限制为私有,对此方法的访问被隔离到定义协议的源文件中.这是它的样子:
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)
    }
}

相关文章

当我们远离最新的 iOS 16 更新版本时,我们听到了困扰 Apple...
欧版/美版 特别说一下,美版选错了 可能会永久丧失4G,不过只...
一般在接外包的时候, 通常第三方需要安装你的app进行测...
前言为了让更多的人永远记住12月13日,各大厂都在这一天将应...