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.
To store them in UserDefaults, we need to implement or confirm Codable to the user-defined class or struct. Codable is a typealias of Decodable & Encodable protocols. It adds the functionality of Encoding and Decoding to the class or struct.
To make set of Person
you need to make it conform to Equatable and Hashable protocols:
class Person: Equatable, Hashable {
var Id: Int
var Name: String
init(id: Int, name: String?) {
self.Id = id
self.Name = name ?? ""
}
var hashValue: Int {
get {
return Id.hashValue << 15 + Name.hashValue
}
}
}
func ==(lhs: Person, rhs: Person) -> Bool {
return lhs.Id == rhs.Id && lhs.Name == rhs.Name
}
Then you can use set of persons like this:
var set = Set<Person>()
set.insert(Person(id: 1, name: "name"))
With Swift 2.0, Hashable and Equitable is a part of NSObject. All you need to do is to override "isEqual" and "var hash:" for the property of interest. In this case: "Id", Set will exclude Person-objects with identical Ids.
class Person: NSObject {
var Id: Int
var Name: String
init(id: Int, name: String?) {
self.Id = id
self.Name = name ?? ""
}
override var hash: Int {
return Id.hashValue
}
override func isEqual(object: AnyObject?) -> Bool {
guard let rhs = object as? Person else {
return false
}
let lhs = self
return lhs.Id == rhs.Id
}
}
func mergeArrays(){
let person1 = Person(id: 1, name: "Tom")
let person2 = Person (id: 2, name: "John")
let person3 = Person(id: 3, name: "Adam")
let downloadedPeople = [person1,person2] //[{NSObject, Id 1, Name "Tom"}, {NSObject, Id 2, Name "John"}]
let peopleStoredLocally = [person1,person3] //[{NSObject, Id 1, Name "Tom"}, {NSObject, Id 3, Name "Adam"}]
let downloadedPeopleSet = Set(downloadedPeople) //{{NSObject, Id 2, Name "John"}, {NSObject, Id 1, Name "Tom"}}
let mergedSet = downloadedPeopleSet.union(peopleStoredLocally) //{{NSObject, Id 2, Name "John"}, {NSObject, Id 3, Name "Adam"}, {NSObject, Id 1, Name "Tom"}}
let mergedArray = Array(mergedSet)//[{NSObject, Id 2, Name "John"}, {NSObject, Id 3, Name "Adam"}, {NSObject, Id 1, Name "Tom"}]
}
UPDATE
Depretation warning when using hashValue:
'Hashable.hashValue' is deprecated as a protocol requirement; conform type 'Person' to 'Hashable' by implementing 'hash(into:)' instead
Following the object Person example, nowadays implementation would be:
class Person: Equatable, Hashable {
let id: Int
let countryId: Int
var name: String
init(id: Int, countryId: Int, name: String) {
self.id = id
self.countryId = countryId
self.name = name
}
func hash(into hasher: inout Hasher) {
hasher.combine(id)
hasher.combine(countryId)
}
static func == (lhs: Person, rhs: Person) -> Bool {
return lhs.id == rhs.id && lhs.countryId == rhs.countryId
}
}
Note: As per documentation the components used for hashing must be the same as the components compared in your type’s == operator implementation.
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