Swift使用委托实现多个协议

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Swift使用委托实现多个协议相关的知识,希望对你有一定的参考价值。

我正在尝试实现一个本身继承多个协议的协议,这些协议都有一个委托成员。是否有一种干净的方法来执行此操作,而不需要为每个协议的委托使用不同的名称?

protocol ProtocolOne {
    var delegate: ProtocolOneDelegate?
}

protocol ProtocolTwo {
    var delegate: ProtocolTwoDelegate?
}

protocol CombinedProtocol: ProtocolOne, ProtocolTwo {

}

protocol CombinedDelegate: ProtocolOneDelegate, ProtocolTwoDelegte {

}

class ProtocolImpl: CombinedProtocol {
    // How can I implement delegate here?
    // I've tried the following options without success:
    var delegate: CombinedDelegate?
    var delegate: protocol<ProtocolOneDelegate, ProtocolTwoDelegate>?
}
答案

你应该能够把它们合二为一:

var delegate: (ProtocolOneDelegate & ProtocolTwoDelegate)?

您现在可以使用这两种协议。

另一答案

在您的代码中,delegate只是一个普通的属性。您可以使用多个协议声明具有相同名称和相同类型的属性,并让类直接或间接地实现它。

如果不同的协议定义了具有相同名称但类型不同的属性,则您将无法进行编译,因为编译器会抱怨重新声明属性和类不确认其中一个协议。

有2种可能的解决方案。最明显的一个是避免使用在其他协议中使用的概率很高的名称 - delegate是一个典型案例。使用不同的命名约定,例如protocol1DelegatedataSourceDelegateapiCallDelegate等。

第二种解决方案包括用方法替换属性。例如:

protocol P1 {
    func test() -> String?
}

protocol P2 {
    func test() -> Int?
}

protocol P3: P1, P2 {

}

class Test : P3 {
    func test() ->  String? { return nil }
    func test() -> Int? { return nil }
}

Swift考虑具有相同参数列表但不同返回类型的函数作为重载。但请注意,如果2个协议使用相同的函数签名(名称,参数和返回类型),则在类中实现时,您将实现该函数一次 - 在某些情况下可能是所需行为,但在其他情况下则不需要。

另一答案

解决方案可能是使用协议扩展(检查extension Combined)。好处是Combined只声明delegateoneDelegatetwoDelegate计算交叉实现。不幸的是,要求将三个变量暴露在课堂外,这可能会带来不便。

// MARK: - Delegates protocols

protocol OneDelegate {
    func oneDelegate(one: One)
}
protocol TwoDelegate {
    func twoDelegate(two: Two)
}
protocol CombinedDelegate: OneDelegate, TwoDelegate {
    func combinedDelegate(combined: Combined)
}


// MARK: - Model protocols

protocol One: class {
    var oneDelegate: OneDelegate? { get }
}

protocol Two: class {
    var twoDelegate: TwoDelegate? { get }
}

protocol Combined: One, Two {
    var delegate: CombinedDelegate? { get }
}

extension Combined {
    var oneDelegate: OneDelegate? {
        return delegate
    }
    var twoDelegate: TwoDelegate? {
        return delegate
    }
}


// MARK: - Implementations

class Delegate: CombinedDelegate {
    func oneDelegate(one: One) {
        print("oneDelegate")
    }

    func twoDelegate(two: Two) {
        print("twoDelegate")
    }

    func combinedDelegate(combined: Combined) {
        print("combinedDelegate")
    }
}

class CombinedImpl: Combined {
    var delegate: CombinedDelegate?

    func one() {
        delegate?.oneDelegate(self)
    }

    func two() {
        delegate?.twoDelegate(self)
    }

    func combined() {
        delegate?.combinedDelegate(self)
    }
}


// MARK: - Usage example

let delegate = Delegate()
let protocolImpl = CombinedImpl()
protocolImpl.delegate = delegate
protocolImpl.one()
protocolImpl.two()
protocolImpl.combined()

以上是关于Swift使用委托实现多个协议的主要内容,如果未能解决你的问题,请参考以下文章

Swift 中不调用协议委托方法

Swift学习第八枪--协议

有没有办法在 Swift 中一次将委托分配给同一类的多个对象?

未为 UITextView 触发委托协议功能

在 Swift 上委托 Objective-C 协议

swift 使用委托和协议向前和向后传递数据