Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift Dictionary with Protocol Type as Key

short question here:

I got a protocol protocol SCResourceModel {..} and a dictionary which shall use this protocol type as key: [SCResourceModel : String]. This obviously does not work, as a key in a dictionary has to conform to the protocol Hashable. Making my SCResourceModel inherit from Hashable or trying something like this [protocol<SCResourceModel, Hashable> : String] obviously does not work as well, since Hashable or Equatable can only be used as generic constraints and not as types themselves.

I watched the WWDC 2015 and in Swift 2.0 it is possible to add constraints to a protocol like: protocol SCResourceModel where Self: Hashable {..} which directly addresses this issue (very nice).

Anyway, my question is: Can I do something similar with the current Swift 1.2 version and somehow use this protocol as the key of a dictionary? Or can anyone propose a nice workaround or something else that I might have overlooked?

The only solution I see at the moment for Swift 1.2, is to transform the protocol to a class which inherits from e.g. NSObject and must be subclassed for further usage in my API.

Thanks for your help!

like image 627
croX Avatar asked Jun 17 '15 20:06

croX


1 Answers

I would probably think in the direction of:

protocol SCResourceModel {
    var hashValue: Int { get }
    func isEqualTo(another: SCResourceModel) -> Bool

    // ...
}

struct SCResourceModelWrapper: Equatable, Hashable {
    let model: SCResourceModel

    var hashValue: Int {
        return model.hashValue ^ "\(model.dynamicType)".hashValue
    }
}

func == (lhs: SCResourceModelWrapper, rhs: SCResourceModelWrapper) -> Bool {
    return lhs.model.isEqualTo(rhs.model)
}

struct SCResourceModelDictionary<T> {
    private var storage = [SCResourceModelWrapper: T]()

    subscript(key: SCResourceModel) -> T? {
        get {
            return storage[SCResourceModelWrapper(model: key)]
        }
        set {
            storage[SCResourceModelWrapper(model: key)] = newValue
        }
    }
}
like image 110
0x416e746f6e Avatar answered Sep 24 '22 19:09

0x416e746f6e