Search code examples
iosswiftassociated-types

Trouble with associatedtype constraints between protocols


I have a protocol:

protocol CellContentViewButtonTappable: CellContentView {
    associatedtype ButtonData
    var delegate: (any CellContentViewButtonTappableDelegate)? { get }
}

and a delegate:

protocol CellContentViewButtonTappableDelegate: AnyObject {
    associatedtype ButtonData
    func buttonTapped(_ data: ButtonData)
}

The point here is that when I call delegate?.buttonTapped(_:) from a class conforming to CellContentViewButtonTappable I want the ButtonData I pass back to be the same as the ButtonData that is in the class conforming to CellContentViewButtonTappableDelegate. But I'm not quite sure how to do this. I've tried things like:

protocol CellContentViewButtonTappable: CellContentView {
    associatedtype ButtonData where ButtonData == CellContentViewButtonTappableDelegate.ButtonData
    var delegate: (any CellContentViewButtonTappableDelegate)? { get }
}

but going down this route has always resulted in the error:

Associated type 'ButtonData' can only be used with a concrete type or generic parameter base

I feel like I'm close and this change added in Swift 4 should allow me to do something like this, but I'm just not getting it right. Would be grateful if someone could point me in the right direction.


Solution

  • Rather than associated type constraints in Swift 4, I think you need the primary associated types feature in Swift 5.7 instead.

    Declare the delegate like this, with ButtonData as its primary associated type:

    protocol CellContentViewButtonTappableDelegate<ButtonData>: AnyObject {
        associatedtype ButtonData
        func buttonTapped(_ data: ButtonData)
    }
    

    In CellContentViewButtonTappable, you can then do:

    var delegate: (any CellContentViewButtonTappableDelegate<ButtonData>)? { get }