Melany
Melany

Reputation: 466

Enum as a key for dictionary

I have a dictionary

var observers: [ObservingType: [MessageObserverManager?]] = .init()

as a key I use here enum, but for some reasons it doesn't work, dictionary doesn't create any object with these keys.

enum ObservingType: Hashable {
case messages(codeId: Int, codeTwoId: Int)
case allMessages
case threadMessages(otherId: Int)

static func == (lhs: ObservingType, rhs: ObservingType) -> Bool {
    return lhs.hashValue == rhs.hashValue
}

func hash(into hasher: inout Hasher) {
    switch self {
    case .messages(let codeId, let codeTwoId):
        hasher.combine(codeId)
        hasher.combine(codeTwoId)
        hasher.combine(1000 / Int.random(in: 1...25))

    case .allMessages:
        hasher.combine(100000 / Int.random(in: 1...25))

    case .threadMessages(let otherId):
        hasher.combine(otherId)
        hasher.combine(100000000 / Int.random(in: 1...25))
    }
}

Cold you advice whats wrong with enum?

guard observers[.allMessages]?.isEmpty ?? false else { observers[.allMessages]?.append(observer)

    return
}

observers[.allMessages] = [observer]

here is the code that I use to add values, and the issue was that I didnt create those array, so the reason wasnt in the enum, sorry and thanks for help!

Upvotes: 0

Views: 290

Answers (1)

rmaddy
rmaddy

Reputation: 318854

Your implementation of == is incorrect. Do not compare hash values. Compare the actual values. Remember, two unequal values are allowed to have the same hash value.

Your implementation of hash should not be making use of random numbers. Remove those lines. The hash value for a given value needs to be steady (at least during a single execution of the app). You can't lookup values in a dictionary of the hash of the keys keep changing.

The simplest solution, in this case, is to let the compiler generate both == and hash(into:). Then your code becomes:

enum ObservingType: Hashable {
    case messages(codeId: Int, codeTwoId: Int)
    case allMessages
    case threadMessages(otherId: Int)
}

It's much simpler and you can now use the enum as keys for a dictionary.

Upvotes: 2

Related Questions