Pure swift set with protocol objects Pure swift set with protocol objects swift swift

Pure swift set with protocol objects


Perhaps there is a better solution, but you can make your class generic:

protocol testProtocol : Hashable {    //}class test<P: testProtocol> {    var s : Set<P>?    init() { }}


One solution is to wrap the set in a class or structure, and constrain the insertion function so that it only accepts items that conform to your protocol and to hashable. You can then use a Set of AnyHashable in the implementation.

For example:

protocol MyProtocol {    func doStuff()}class MyProtocolSet {    var set = Set<AnyHashable>()    func insert<T>(_ item: T) where T: MyProtocol, T: Hashable {        set.insert(AnyHashable(item))    }    func iterate( doing: (MyProtocol) -> Void ) {        for item in set {            doing(item as! MyProtocol)        }    }}struct Foo: MyProtocol, Hashable {    func doStuff() { print("foo") }}struct Bar: MyProtocol, Hashable {    func doStuff() { print("bar") }}func test() {    let set = MyProtocolSet()    set.insert(Foo())    set.insert(Bar())    set.iterate { (item: MyProtocol) in        item.doStuff()    }}

By putting the constraints on the insertion function, you're saying "this set has to contain things that conform to the protocol, and are hashable", without actually constraining the protocol to being hashable.

It would be even nicer if the wrapping set class could itself be generic, and take in the protocol to conform to, but I haven't figured out if that is possible yet!


I know this isn't a Set (like the question asked for), but you can use an NSHashTable instead of a Set. You will have to expose your protocol to objc though. Although not a Set, if you're just looking to store a collection of protocol objects without having to conform to Hashable, this will work:

@objc protocol testProtocol { }class Object {    var s: NSHashTable<testProtocol>!}

That way you can use the add and remove functions that are provided.

Furthermore, if you are storing observers or anything similar, you can initialize the hash table with NSHashTable.weakObjects() which will ensure the objects aren't retained.

Here's more about the NSHashTable: https://developer.apple.com/documentation/foundation/nshashtable