2016-01-03 9 views
5

Mam podklasa PFUser - myuser klasy z realizacji Equatable funkcji porównywania objectIds ten sposób:Swift Array.contains() nie wywołać Equatable funkcję PFUser podklasy

func ==(left: MYUser, right: MYUser) -> Bool { 
    return left.objectId == right.objectId 
} 

Ale kiedy wywołuję metodę Array.contains(), nie wywołuje tej implementacji funkcji Równoważna, która prowadzi do niepoprawnych wyników. Na przykład, w tym przypadku:

let hasUser = self.selectedUsers.contains(currentUser) 

hasUser się fałszywe razie selectedUsers tablica zawiera inny obiekt w pamięci, ale z tą samą objectid jak w CurrentUser.

Co interesujące, implementacja funkcji Equatable jest wywoływana bezpośrednio. Tutaj:

var hasUser = false 
for itUser in self.selectedUsers { 
    if itUser == currentUser { 
    hasUser = true 
    break 
    } 
} 

== operator pomyślnie nazwano i hasUser ma poprawne wartości dla różnych obiektów pamięci, ale z tym samym objectID

co może być przyczyną tego?

AKTUALIZACJA. Oto myuser klasa:

class MYUser: PFUser { 

    // MARK: - Parse Object 

    @NSManaged var avatarFile: PFFile? 
    @NSManaged var fullName: String? 

    // MARK: - PFSubclassing Methods (through PFUser) 

    override class func initialize() { 
     struct Static { 
      static var onceToken : dispatch_once_t = 0; 
     } 
     dispatch_once(&Static.onceToken) { 
      self.registerSubclass() 
     } 
    } 
} 

func ==(left: MYUser, right: MYUser) -> Bool { 
    return left.objectId == right.objectId 
} 
+1

mam żadnego doświadczenia z Parse.com, ale może to być związane: http://stackoverflow.com/questions/33319959/nsobject-subclass-in-swift-hash-vs-hashvalue-isequal-vs - spróbuj zastąpić 'isEqual:' zamiast '=='. –

+0

@MartinR Nie sądzę, że jest to jedyna kwestia współdziałania Parse i ObjC.Stworzyłem czysty Swift MWE, a także przeciążono '==' dla podklasy nie jest wywoływane w 'zawiera'. –

+0

Może to nie ma znaczenia, ale czy możesz pokazać nam, jak zdefiniowano 'MYUser'? –

Odpowiedz

9

myślę, czy to jest NSObject problem.

class MYUserNSObject: NSObject { 
    dynamic var fullName: String 

    init(fullName: String) { 
     self.fullName = fullName 
     super.init() 
    } 
} 

func ==(left: MYUserNSObject, right: MYUserNSObject) -> Bool { 
    return left.fullName == right.fullName 
} 

let objectUsers = [MYUserNSObject(fullName: "a"), MYUserNSObject(fullName: "b")] 
let objectResult = objectUsers.contains(MYUserNSObject(fullName: "a")) 
print("\(result)") 

Drukuje fałsz.

class MYUserSwift: Equatable { 
    var fullName: String 

    init(fullName: String) { 
     self.fullName = fullName 
    } 
} 

func ==(left: MYUserSwift, right: MYUserSwift) -> Bool { 
    return left.fullName == right.fullName 
} 

let swiftUsers = [MYUserSwift(fullName: "a"), MYUserSwift(fullName: "b")] 
let swiftResult = swiftUsers.contains(MYUserSwift(fullName: "a")) 
print("\(swiftResult)") 

Wydruk jest prawdziwy.


Wreszcie, dodając -isEqual:, naprawiłem to.

class MYUserNSObject: NSObject { 
    dynamic var fullName: String 

    init(fullName: String) { 
     self.fullName = fullName 
     super.init() 
    } 

    override func isEqual(object: AnyObject?) -> Bool { 
     guard let user = object as? MYUserNSObject else { return false } 
     return self == user 
    } 
} 

func ==(left: MYUserNSObject, right: MYUserNSObject) -> Bool { 
    return left.fullName == right.fullName 
} 

let objectUsers = [MYUserNSObject(fullName: "a"), MYUserNSObject(fullName: "b")] 
let objectResult = objectUsers.contains(MYUserNSObject(fullName: "a")) 
print("\(objectResult)") 

Wydruk jest prawdziwy.


Aktualizacja dla Swift 4.0

class MYUserNSObject: NSObject { 
    @objc var fullName: String 

    init(fullName: String) { 
     self.fullName = fullName 
     super.init() 
    } 

    override func isEqual(_ object: Any?) -> Bool { 
     guard let user = object as? MYUserNSObject else { return false } 
     return self.fullName == user.fullName 
    } 
} 

let objectUsers = [MYUserNSObject(fullName: "a"), MYUserNSObject(fullName: "b")] 
let objectResult = objectUsers.contains(MYUserNSObject(fullName: "a")) 
print("\(objectResult)") 

Drukuje prawdziwej.

Uwaga: nie jest już wymagana funkcja ==(left:right:).

let success = MYUserNSObject(fullName: "a") == objectUsers[0] 
print("success should be true: \(success)") 

let failure = MYUserNSObject(fullName: "a") == objectUsers[1] 
print("failure should be false: \(failure)") 
+1

Tak, wygląda na to, że Array.contains() wywołuje specjalnie metodę '-isEquals:' dla podklas NSObject. Dziękuję Ci. –

+0

Hej Jeffrey, dziękuję bardzo za dostarczenie rozwiązania. To zaoszczędziło mi tyle czasu. Jest to najlepsza odpowiedź do porównania dwóch klas niestandardowych z wykorzystaniem przeciążenia operatora ==. Jeszcze raz dziękuję :) –

+0

Aktualizacja najnowszego Swifta, prototypem dla isEqual jest "Any?" nie "AnyObject?" –

Powiązane problemy