I am working on a project built by using Swift, and I am trying to create a dictionary to store objects of a custom class called Pixel(KEY, for storing colour information such as RGB values) and int values (Value, for counting how many times the same colour appearing on the same image).
If this is in C#, the working code should be:
Dictionary<Pixel, int> colorDictionary = new Dictionary< Pixel, int> ()
;
In Swift, I tried:
var colorDictionary = Dictionary<Pixel, Int>()
However, the error I got:
"Type 'Pixel' does not conform to protocol 'Hashable'"
What should I do to solve this? Thanks very much!
Any type that conforms to the Hashable protocol can be used as a dictionary's Key type, including all of Swift's basic types. You can use your own custom types as dictionary keys by making them conform to the Hashable protocol.
Modifying Key-Value Pairs To change the value of a key-value pair, use the . updateValue() method or subscript syntax by appending brackets [ ] with an existing key inside them to a dictionary's name and then adding an assignment operator ( = ) followed by the modified value.
Use explicit variable typing, or let Swift infer the type of the variable based on the value assigned to it. Use the formal specified generic struct notation Dictionary<String,Double> , or use the built-in "syntactic sugar" for describing a dictionary type [String:Double] .
Sets are unordered collections of unique values. Dictionaries are unordered collections of key-value associations. Arrays, sets, and dictionaries in Swift are always clear about the types of values and keys that they can store. This means that you can't insert a value of the wrong type into a collection by mistake.
From swift 4.2, hashValue
is deprecated as a Hashable requirement.
Now if you want to customize how your type implements Hashable
, you can override the hash(into:)
method instead of hashValue. The hash(into:)
method passes a Hasher object by reference, which you call combine(_:)
on to add the essential state information of your type.
class Pixel {
var alpha, red, green, blue : Int
}
// Hashable implementation
extension Pixel : Hashable {
func hash(into hasher: inout Hasher) {
hasher.combine(self.red)
hasher.combine(self.green)
hasher.combine(self.blue)
hasher.combine(self.alpha)
}
}
Continuing on with what Andy Ibanez posted. A shortcut to implementing a hashValue is to piggyback off String's hashValue. You could do something like this.
class Pixel: Hashable {
var r:Int = 0;
var g:Int = 0;
var b:Int = 0;
var a:Int = 0;
var hashValue: Int {
get {
return "\(r)\(g)\(b)\(a)".hashValue;
}
}
}
You also need an Equatable function because hashValues in this case are merely a quick check for verifying two objects are not equal. Since it is possible for two objects to have the same hashValue, but not be equal, you still need to implement == to define equality like below.
func ==(lhs: Pixel, rhs: Pixel) -> Bool{
if lhs.r != rhs.r{
return false;
}
if lhs.g != rhs.g{
return false;
}
if lhs.b != rhs.b{
return false;
}
if lhs.a != rhs.a{
return false;
}
return true;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With