2016-01-03 2 views
5

Ich habe eine Unterklasse von PFUser - myuser Klasse mit der Implementierung von gleichzusetzen Funktion für objectIds auf diese Weise zu vergleichen:Swift Array.contains() stellt nicht gleichzusetzen Funktion von PFUser Unterklasse

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

Aber wenn ich Array.contains() Methode aufrufen, ruft es nicht diese Implementierung von Equatable Funktion, die zu falschen Ergebnissen führt. Zum Beispiel hier:

let hasUser = self.selectedUsers.contains(currentUser) 

hasUser werden falsch wenn selectedUsers Array unterschiedliches Speicherobjekt aber mit dem gleichen objectId wie in current enthält.

Was interessant, Gleichwertige Funktionsimplementierung heißt im direkten Einsatz. Hier:

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

== Operatoren erfolgreich aufgerufen wurde und hasUser richtige Werte für verschiedene Speicherobjekte hat aber mit dem gleichen objectId

Was die Ursache davon sein kann?

UPDATE. Hier ist myuser Klasse:

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

Ich habe keine Erfahrung mit Parse.com, aber in Beziehung gesetzt werden kann: http://stackoverflow.com/questions/33319959/nsobject-subclass-in-swift-hash-vs-hashvalue-isequal-vs - Überschreibe 'isEqual:' anstelle von '=='. –

+0

@MartinR Ich denke nicht, dass es die einzige Frage der Interoperabilität von Parse und ObjC ist.Ich habe pure Swift MWE erstellt und auch '_=' für Unterklasse überladen wird nicht in 'contains' aufgerufen. –

+0

Vielleicht ist es nicht relevant, aber können Sie uns zeigen, wie 'MYUser' definiert ist? –

Antwort

9

Ich denke, dies ist ein 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)") 

Druckt falsch.

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)") 

Drucke wahr.


Schließlich, indem ich -isEqual: hinzufüge, reparierte ich dieses.

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)") 

Druckt wahr.


für 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)") 
wahr

Drucke aktualisiert.

Hinweis: Es wird keine ==(left:right:) Funktion mehr benötigt.

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

hinzugefügt. Ja, es scheint, dass Array.contains() speziell auf '-isEquals:' Methode für NSObject-Unterklassen aufruft. Vielen Dank. –

+0

Hey Jeffrey, vielen Dank für die Bereitstellung einer Lösung. Das hat mir so viel Zeit erspart. Dies ist die beste Lösung, um zwei benutzerdefinierte Klassen mit dem Operator == operator overloading zu vergleichen. Danke nochmal :) –

+0

Update für den neuesten Swift, der Prototyp für isEqual ist "Any?" nicht "AnyObject?" –