2
votes

How can I perform conformance check against protocol with AssociatedType. Xcode shows error:

Protocol 'MyListener' can only be used as a generic constraint because it has Self or associated type requirements

My ultimate goal is to extract "MyListener.section" from an array of weakObjects, where the handler matches the function argument.

Note. The NSPointerArray of weakObjects is suppose to capture different types of MyListeners.

public class MyHandler<O,E> {
    var source = [O]()
    var dest = [E]()
}
public protocol MyListener:class {
    var section: Int {get}
    associatedtype O
    associatedtype E
    var handler: MyHandler<O,E>? { get }
}

public class MyAnnouncer {
    private let mapWeakObjects: NSPointerArray = NSPointerArray.weakObjects()
    public func add<L: MyListener>(listener: L) {
        let pointer = Unmanaged.passUnretained(listener).toOpaque()
        mapWeakObjects.addPointer(pointer)
    }
    public func search<O, E> (h:MyHandler<O,E>) -> [Int] {
        _ = mapWeakObjects.allObjects.filter { listener in
            if listener is MyListener { // Compilation failed
            }
            if let _ = listener as? MyListener { //Compilation error
            }
            if listener is MyListener.Type { //Compilation failed
            }
        }
        return [] // ultimate goal is to extract corresponding [MyListener.section].
    }
}
1

1 Answers

0
votes

Unfortunately, Swift doesn't support protocols with AssociatedType to conformance.

You should try to use Type Erasure. One of the way is to implement type erasure by creating new AnyType class. Here is another way to release type erasure (example from the internet)

protocol SpecialValue { /* some code*/ }

protocol TypeErasedSpecialController {
  var typeErasedCurrentValue: SpecialValue? { get }
}

protocol SpecialController : TypeErasedSpecialController {
  associatedtype SpecialValueType : SpecialValue
  var currentValue: SpecialValueType? { get }
}

extension SpecialController {
  var typeErasedCurrentValue: SpecialValue? { return currentValue }
}

extension String : SpecialValue {}

struct S : SpecialController {
  var currentValue: String?
}

var x: Any = S(currentValue: "Hello World!")
if let sc = x as? TypeErasedSpecialController { // Now we can perform conformance
  print(sc.typeErasedCurrentValue) 
}