将通用委托添加到 Swift 中的基类

问题描述

理想情况下,我想创建一个 BaseViewController 类,该类接受(委托的)协议类型并具有弱变量作为委托。像这样:

class BaseViewController<Delegate: AnyObject> {
    weak var delegate: Delegate?

    init(delegate: Delegate) {
        self.delegate = delegate
        super.init(...)
    }
}

然后像这样从视图控制器继承:

protocol MyDelegate: AnyObject { 
    func funcA()
    func funcB()
}  

class SomeViewController: BaseViewController<MyDelegate> {
    func doSomething() {
        delegate?.funcA()
    }
}

这不起作用,因为编译器抱怨:

'BaseViewController' 要求 'MyDelegate' 是一个类类型

我该如何解决这个问题来实现我的需要?
提前致谢:)

解决方法

那是因为在 swift 协议中不向他们自己确认,你不能使用“MyProtocol”作为确认协议“MyDelegate”的具体类型

你更愿意做的是

[{
        "id": "1","ItemSold" : 44,"AnotherAtt" : 567
    },{
        "id": "2","ItemSold" : 1213,"AnotherAtt" : 656
    }]

编辑 1:

正如 OP 在评论中提到的,他试图在 protocol MyDelegate: AnyObject { func funcA() func funcB() } class BaseViewController<Delegate: MyDelegate> { weak var delegate: Delegate? init(delegate: Delegate) { self.delegate = delegate super.init(...) //keeping OPs code as is } } class SomeOtherDelegateClass: MyDelegate { func funcA() { //some code here } func funcB() { //some code here } } class SomeViewController: BaseViewController<SomeOtherDelegateClass> { func doSomething() { self.delegate?.funcA() } } 中引入一个泛型属性,该属性将简单地持有对其类由 BaseViewController 的子类使用泛型决定/声明的任何实例的弱引用,我稍微简化了上面的答案

试试这个

BaseViewController

TBH,我真的看不出这种设计有多大好处!可能你需要重新审视代码结构,看看你是否能想出更好的代码结构:)

,

您应该将您的委托设置为 BaseViewController 中泛型类型 T 的约束:

protocol MyDelegate: AnyObject {
    func funcA()
    func funcB()
}

class Delegated1: MyDelegate {
    func funcA() { print("A1") }
    func funcB() {}
}

class Delegated2: MyDelegate {
    func funcA() { print("A2") }
    func funcB() {}
}

class BaseViewController<T: MyDelegate>: UIViewController {
    var delegate: T?

    func doSomething() {
        delegate?.funcA()
    }
}

class SomeViewController1: BaseViewController<Delegated1> {}
class SomeViewController2: BaseViewController<Delegated2> {}

class TestClass {
    let viewController1: SomeViewController1 = {
        let viewController = SomeViewController1(nibName: nil,bundle: nil)
        viewController.delegate = .init()
        return viewController
    }()

    let viewController2: SomeViewController2 = {
        let viewController = SomeViewController2(nibName: nil,bundle: nil)
        viewController.delegate = .init()
        return viewController
    }()


    // prints:
    // A1
    // A2
    func myFunc() {
        viewController1.doSomething()
        viewController2.doSomething()

    }
}