2015-09-06 6 views
29

Для моего приложения IOS У меня есть модель что-то вродеКак создать набор пользовательских объектов (Swift)?

class Person { 
    var Id: Int 
    var Name: String 

    init(id: Int, name: String?) { 
     self.Id = id 
     self.Name = name ?? "" 
    } 
} 

Тогда позже в моей ViewController, когда я загрузить данные с сервера, я добавить некоторые люди в массив

class ViewController: UIViewController { 
    var people:[Person] = [] 

    override func viewDidLoad() { 
     self.loadPeople() 
    } 

    func loadPeople() { 
     // This data will be coming from a server request 
     // so is just sample. It could have users which 
     // already exist in the people array 

     self.people.append(Person(id: "1", name: "Josh")) 
     self.people.append(Person(id: "2", name: "Ben")) 
     self.people.append(Person(id: "3", name: "Adam")) 
    } 
} 

То, что я сейчас нахожусь попытка todo превратить массив people в Set<Person>, чтобы он не добавлял дубликаты. Возможно ли это сделать или мне нужно изменить свою логику?

ответ

38

Чтобы сделать множество Person вы должны сделать это соответствовать Equatable и Hashable протоколов:

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 
} 

Затем вы можете использовать множество людей, как это:

var set = Set<Person>() 
set.insert(Person(id: 1, name: "name")) 
+2

Я лично использую 'XOR' для объединения хэшей, но +1 для включения в ваш ответ протокола' Hashable'. –

+4

Hashable наследует от Equatable, поэтому объявление класса как класса Person: Hashable {...} 'было бы достаточно. Конечно, добавление Equatable явно не наносит вреда. –

+1

@ egor.zhdan не могли бы вы объяснить сдвиг бит 15 часть и почему вы использовали 15 там? –

6

С Swift 2.0, Hashable и Equitable является частью NSObject. Все, что вам нужно сделать, это переопределить «isEqual» и «var hash:» для интересующего свойства. В этом случае: «Id», Set будет исключать объекты Person с идентичными идентификаторами.

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"}] 

    } 
+5

Вы, вероятно, не должны использовать типы objC для быстрого приложения, если вам действительно не нужно. Поэтому я бы рекомендовал использовать автономные протоколы вместо наследования из NSObject. – herby

Смежные вопросы