Swift dictionary with protocol type as key

short question here:

I got a protocol protocol SCResourceModel {..}and a dictionary, which is to use this type of protocol as the key: [SCResourceModel : String]. This clearly does not work, since the key in the dictionary must conform to the protocol Hashable. Doing my inheritance SCResourceModelfrom Hashableor attempting something like this [protocol<SCResourceModel, Hashable> : String]obviously does not work, since Hashableor Equatablecan only be used as general constraints, and not as the types themselves.

I watched WWDC 2015, and in Swift 2.0 you can add restrictions to a protocol such as: protocol SCResourceModel where Self: Hashable {..}which directly solves this problem (very nice).

In any case, my question is: can I do something similar with the current version of Swift 1.2 and somehow use this protocol as a dictionary key? Or can someone suggest a good workaround or something else that I might be missing out on?

The only solution that I see at the moment for Swift 1.2 is to convert the protocol to a class that inherits, for example, NSObject and needs to be subclassed for future use in my API.

Thank you for your help!

+3
source share
2 answers

I would probably think in the direction:

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
        }
    }
}
+5
source

, , . , . ( )

, Swift, Objective-C, , , Swift:

// With a protocol declared...
@protocol TestProtocol <NSObject>
@end

@implementation

// Inside the implementation you can use NSStringFromProtocol()
Protocol *proto = @protocol(TestProtocol);
NSLog(@"Protocol: %@", NSStringFromProtocol(proto));

@end

:

Protocol: TestProtocol

@protocol - , , Swift, , Objective-C. , !

+2

Source: https://habr.com/ru/post/1623537/


All Articles