ios - 可以动态地将逻辑附加到方法吗?

标签 ios swift swift2 protocol-extension

我想动态地将闭包附加到类的初始化中的另一个方法。例如,对于 UIViewController,我想添加一个扩展,以便我可以在 viewDidLoad 事件中注入(inject)代码。我尝试了类似下面的方法,但它不起作用:

class BaseViewController: UIViewController, MyProtocol {

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        // Setup and bind
        configure()
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        // Call MyProtocol.myDidLoad but not explicitly!
    }

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)

        // Call viewWillAppear but not explicitly!
    }

}

protocol MyProtocol { }

extension MyProtocol where Self: UIViewController {

    func configure() {
        // Something like below isn't possible???
        self.viewDidLoad += myDidLoad
        self.viewWillAppear += myWillAppear
    }

    func myDidLoad() {
        // Something
    }

    func myWillAppear() {
        // Something
    }
}

是否可以在不从 UIViewController 显式调用协议(protocol)函数的情况下实现这一点?我不想遍历我所有的类并为每个函数调用协议(protocol)函数。那将是乏味的、冗余的代码,并且很容易被忽略。有没有更优雅的方式?

更新:

考虑到限制,下面是我能想到的唯一方法,但它使用继承而不是组合,仍然需要我显式调用协议(protocol)扩展函数,这不是我想要的做:

class FirstViewController: BaseViewController {

}

class BaseViewController: UIViewController, MyProtocol, MyProtocol2, MyProtocol3 {

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        // Configure protocols
        configure(self as MyProtocol)
        configure(self as MyProtocol2)
        configure(self as MyProtocol3)
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        // Load protocols
        viewDidLoad(self as MyProtocol)
        viewDidLoad(self as MyProtocol2)
        viewDidLoad(self as MyProtocol3)
    }

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)

        // Prerender protocols
        viewWillAppear(self as MyProtocol)
        viewWillAppear(self as MyProtocol2)
        viewWillAppear(self as MyProtocol3)
    }

}

protocol MyProtocol { }

extension MyProtocol where Self: UIViewController {

    func configure(delegate: MyProtocol) {
        print("MyProtocol.configure")
    }

    func viewDidLoad(delegate: MyProtocol) {
        print("MyProtocol.viewDidLoad")
    }

    func viewWillAppear(delegate: MyProtocol) {
        print("MyProtocol.viewWillAppear")
    }
}

protocol MyProtocol2 { }

extension MyProtocol2 where Self: UIViewController {

    func configure(delegate: MyProtocol2) {
        print("MyProtocol2.configure")
    }

    func viewDidLoad(delegate: MyProtocol2) {
        print("MyProtocol2.viewDidLoad")
    }

    func viewWillAppear(delegate: MyProtocol2) {
        print("MyProtocol2.viewWillAppear")
    }
}

protocol MyProtocol3 { }

extension MyProtocol3 where Self: UIViewController {

    func configure(delegate: MyProtocol3) {
        print("MyProtocol3.configure")
    }

    func viewDidLoad(delegate: MyProtocol3) {
        print("MyProtocol3.viewDidLoad")
    }

    func viewWillAppear(delegate: MyProtocol3) {
        print("MyProtocol3.viewWillAppear")
    }
}

//Output:
//MyProtocol.configure
//MyProtocol2.configure
//MyProtocol3.configure
//MyProtocol.viewDidLoad
//MyProtocol2.viewDidLoad
//MyProtocol3.viewDidLoad
//MyProtocol.viewWillAppear
//MyProtocol2.viewWillAppear
//MyProtocol3.viewWillAppear

这违背了面向协议(protocol)编程的全部目的。在 iOS 开发范围内工作时,是否有一种 Swift 可以处理的优雅方法,或者 POP 在这种情况下不起作用?

最佳答案

你想做的事情是不可能的,因为 Swift 和 Objective-C 都是单继承语言。

扩展只能添加额外的方法,不能覆盖方法。只有子类可以覆盖现有类中的方法。考虑多个扩展覆盖同一个方法的情况——应该调用哪个?所有这些?如果是这样,顺序是什么?参见 The Diamond Problem

最简单的方法是创建一个提供所需功能的 UIViewController 子类。尽管程序员可以创建一个符合协议(protocol)但不继承正确父类(super class)的类,但考虑到类和协议(protocol)是在同一行输入的,这将是一个非常愚蠢的错误。

关于ios - 可以动态地将逻辑附加到方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35661229/

相关文章:

ios - Swift UITableView 真的很慢

ios - 无法使用类型为 '[(String)]?' 的索引下标类型为 'Int' 的值

ios - "' 在应用程序扩展上共享 ' is unavailable: Use view controller based solutions where appropriate instead"

iphone - 在 iOS 中解析 XML/'screen scraping' 的最佳方法是什么? UIWebview 还是 NSXMLParser?

ios - 以编程方式动态本地化 Storyboard

ios - Realm - 返回数组列表

swift - 使用 Swift 2.1.1 解析 TMX 文件时出错

ios - 场景数据错误 : Type of expression is ambiguous without more context

android - 登录在 Ionic View 应用程序中不起作用

ios - 删除 SpriteKit 中的特定节点