Created
April 2, 2020 20:38
-
-
Save austenstrine/c176ab894d2f2661bcedbfc3992dddf2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
protocol PropertyLoopable { | |
func allProperties() -> [String: Any?] | |
} | |
extension Optional { | |
func unwrappedDebugString() -> String { | |
switch self { | |
case .some(let value): | |
return "\(value)" | |
case .none: | |
return "nil" | |
} | |
} | |
} | |
final class LoopableObject: PropertyLoopable, Hashable { | |
static let classForCoder = LoopableObject.self | |
let anOptionalInt:Int64? | |
let anOptionalString:String? | |
let anOptionalBool:Bool? | |
let anOptionalDouble:Double? | |
init(int:Int64?, string:String?, bool:Bool?, double:Double?) { | |
anOptionalBool = bool | |
anOptionalString = string | |
anOptionalInt = int | |
anOptionalDouble = double | |
} | |
func allProperties() -> [String: Any?] { | |
var result: [String: Any?] = [:] | |
let mirror = Mirror(reflecting: self) | |
for (labelMaybe, valueMaybe) in mirror.children { | |
guard let label = labelMaybe else { | |
continue | |
} | |
result[label] = valueMaybe | |
} | |
return result | |
} | |
static func == (lhs: LoopableObject, rhs: LoopableObject) -> Bool { | |
let lhsProperties = lhs.allProperties() | |
let rhsProperties = rhs.allProperties() | |
var position = 0 | |
for (key, optionalProperty) in lhsProperties { | |
position += 1 | |
print(" \(position)") | |
print(" stringcomparison: \(rhsProperties[key].unwrappedDebugString()) != \(optionalProperty.unwrappedDebugString())") | |
if rhsProperties[key].unwrappedDebugString() != optionalProperty.unwrappedDebugString() { | |
return false | |
} | |
} | |
return true | |
} | |
func hash(into hasher: inout Hasher) { | |
let properties = self.allProperties().sorted(by: {$0.key < $1.key}) | |
print("\(type(of: self))") | |
hasher.combine("\(type(of: self))") | |
var position = 0 | |
print("begin hash calculation") | |
for (key,property) in properties { | |
position += 1 | |
print(" \(position) : \(key)") | |
hasher.combine(key) | |
hasher.combine(property.unwrappedDebugString()) | |
print(" \(property.unwrappedDebugString())") | |
hasher.combine("\(type(of: property))") | |
print(" \(type(of: property))") | |
} | |
print("complete") | |
} | |
} | |
let objectOne = LoopableObject(int: 257, string: nil, bool: false, double: 0.01) | |
let objectTwo = LoopableObject(int: 257, string: nil, bool: false, double: 0.01) | |
print("objectOne.hashValue == objectTwo.hashValue : \(objectOne.hashValue == objectTwo.hashValue)") | |
print("objectOne == objectTwo : \(objectOne == objectTwo)") | |
/*console results | |
LoopableObject | |
begin hash calculation | |
1 : anOptionalBool | |
Optional(false) | |
Optional<Any> | |
2 : anOptionalDouble | |
Optional(0.01) | |
Optional<Any> | |
3 : anOptionalInt | |
Optional(257) | |
Optional<Any> | |
4 : anOptionalString | |
nil | |
Optional<Any> | |
complete | |
LoopableObject | |
begin hash calculation | |
1 : anOptionalBool | |
Optional(false) | |
Optional<Any> | |
2 : anOptionalDouble | |
Optional(0.01) | |
Optional<Any> | |
3 : anOptionalInt | |
Optional(257) | |
Optional<Any> | |
4 : anOptionalString | |
nil | |
Optional<Any> | |
complete | |
objectOne.hashValue == objectTwo.hashValue : true | |
1 | |
stringcomparison: Optional(Optional(false)) != Optional(false) | |
objectOne == objectTwo : false | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment