I'd like to build a hashable value to be used for my dictionary's key. It should consist of a structure with two strings and an NSDate. I'm not sure I built my hashValue
getter correctly below:
// MARK: comparison function for conforming to Equatable protocol
func ==(lhs: ReminderNotificationValue, rhs: ReminderNotificationValue) -> Bool {
return lhs.hashValue == rhs.hashValue
}
struct ReminderNotificationValue : Hashable {
var notifiedReminderName: String
var notifiedCalendarTitle: String
var notifiedReminderDueDate: NSDate
var hashValue : Int {
get {
return notifiedReminderName.hashValue &+ notifiedCalendarTitle.hashValue &+ notifiedReminderDueDate.hashValue
}
}
init(notifiedReminderName: String, notifiedCalendarTitle: String, notifiedReminderDueDate: NSDate) {
self.notifiedReminderName = notifiedReminderName
self.notifiedCalendarTitle = notifiedCalendarTitle
self.notifiedReminderDueDate = notifiedReminderDueDate
}
}
var notifications: [ReminderNotificationValue : String] = [ : ]
let val1 = ReminderNotificationValue(notifiedReminderName: "name1", notifiedCalendarTitle: "title1", notifiedReminderDueDate: NSDate())
let val2 = ReminderNotificationValue(notifiedReminderName: "name1", notifiedCalendarTitle: "title1", notifiedReminderDueDate: NSDate())
notifications[val1] = "bla1"
notifications[val2] = "bla2"
notifications[val2] // returns "bla2".
notifications[val1] // returns "bla1". But I'd like the dictionary to overwrite the value for this to "bla2" since val1 and val2 should be of equal value.
The problem is not your hashValue
implementation, but the ==
function.
Generally, x == y
implies x.hashValue == y.hashValue
, but not
the other way around. Different objects can have the same hash value.
Even
var hashValue : Int { return 1234 }
would be an ineffective, but valid hash method.
Therefore in ==
, you have to compare the two objects for exact
equality:
func ==(lhs: ReminderNotificationValue, rhs: ReminderNotificationValue) -> Bool {
return lhs.notifiedReminderName == rhs.notifiedReminderName
&& lhs.notifiedCalendarTitle == rhs.notifiedCalendarTitle
&& lhs.notifiedReminderDueDate.compare(rhs.notifiedReminderDueDate) == .OrderedSame
}
Another problem in your code is that the two invocations
of NSDate()
create different dates, as NSDate
is an absolute
point in time, represented as a floating point number with sub-second
precision.