Conforming to Hashable protocol?
You're missing the declaration:
struct DateStruct: Hashable {
And your ==
function is wrong. You should compare the three properties.
static func == (lhs: DateStruct, rhs: DateStruct) -> Bool {
return lhs.year == rhs.year && lhs.month == rhs.month && lhs.day == rhs.day
}
It's possible for two different values to have the same hash value.
Make a swift protocol conform to Hashable
Deriving the protocol from Hashable
and using a type eraser might help here:
protocol SomeLocation: Hashable {
var name: String { get }
var coordinates: Coordinate { get }
}
struct AnyLocation: SomeLocation {
let name: String
let coordinates: Coordinate
init<L: SomeLocation>(_ location: L) {
name = location.name
coordinates = location.coordinates
}
}
You then can simply declare the protocol conformance on the structs, and if Coordinate
is already Hashable
, then you don't need to write any extra hashing code code, since the compiler can automatically synthesize for you (and so will do for new types as long as all their properties are Hashable
:
struct ShopLocation: SomeLocation, Decodable {
var name: String
var coordinates: Coordinate
}
struct CarLocation: SomeLocation, Decodable {
var name: String
var coordinates: Coordinate
}
If Coordinate
is also Codable
, then you also can omit writing any code for the encoding/decoding operations, the compile will synthesize the required methods (provided all other properties are already Codable
).
You can then use the eraser within the annotation class by forwardingn the initializer constraints:
final class LocationAnnotation: NSObject, MKAnnotation {
let location: AnyLocation
init<L: SomeLocation>(location: L) {
self.location = AnyLocation(location)
super.init()
}
override var hash: Int {
location.hashValue
}
override func isEqual(_ object: Any?) -> Bool {
(object as? LocationAnnotation)?.location == location
}
}
Swift - Can I make a protocol Hashable?
As @Leo Dabus mentioned in his comment, you should probably use another name for your protocol due to native Foundation.Data
type existence.
Either way, using the following code you can implement Hashable
protocol into your Data
protocol:
public protocol Data: Hashable {
var state: [String: Any] { get set }
var objectId: String? { get set }
}
public extension Data {
var objectId: String? {
get {
return self.state["objectId"] as? String
}
set {
self.state["objectId"] = newValue
}
}
static func == (lhs: Self, rhs: Self) -> Bool {
return lhs.objectId == rhs.objectId
}
func hash(into hasher: inout Hasher) {
hasher.combine(self.objectId ?? "")
}
}
Although this will have as a side effect that protocol Data
can only be used as a generic constraint because it has Self or associated type requirements:
Meaning that you can now on use the Data
protocol like this:
func myFunc<T: Data>(data: T) {
}
Swift - Type '' does not conform to protocol 'Hashable'
Supply your own implementation for Hashable
by overriding hash(into:)
and call combine
on all the relevant properties.
struct ListAction: Hashable {
static func == (lhs: ListAction, rhs: ListAction) -> Bool {
return lhs.label == rhs.label && lhs.command == rhs.command
}
func hash(into hasher: inout Hasher) {
hasher.combine(label)
hasher.combine(command)
}
let label: String
let action: (() -> Void)? = nil
let command: Command? = nil
}
Related Topics
How to Convert Nsurl to String in Swift
Mutate Function Parameters in Swift
How to Add Caching to Asyncimage
How to Select a Contact with Abpeoplepickernavigationcontroller in Swift
What Language Is Swift Written In
How to Implement Hash(Into:) from Hashvalue in Swift
Get Playground to Display All Loop Results
How to Prevent Actor Reentrancy Resulting in Duplicative Requests
How to Implement a Spritekit Timer
Why Is There a Memory Leak at String Creation in Swift
Uialertcontroller Change Font Color
Why Don't Structs Have Deinitializers in Swift Like Classes