it-swarm.com.de

Die eleganteste Art, zwei Optionals in Swift zu vergleichen

Ich habe zwei AnyObject?-Variablen, die ich für Referenzgleichheit vergleichen möchte:

var oldValue: AnyObject?
var newValue: AnyObject?
...
if oldValue != newValue {
    changed = true
}

Dies funktioniert jedoch nicht, da ich zwei Optionals anscheinend nicht direkt vergleichen kann. Ich möchte das Verhalten so, als würde ich ids in Objective-C vergleichen, das heißt:

  • true wenn beide nil sind
  • true wenn beide einen Wert haben und die Werte auch gleich sind
  • false sonst

Gibt es eine elegante Möglichkeit, dies in Swift zu schreiben (idealerweise ohne eine benutzerdefinierte Erweiterung zu schreiben)?

Das ist das Beste, was ich mir ausgedacht habe:

if !(oldValue != nil && newValue != nil && oldValue == newValue)

Nicht sehr hübsch :(

13
devios1

Sie können !== verwenden 

Von Die schnelle Programmiersprache

Swift bietet auch zwei Identitätsoperatoren (=== und !==), mit denen Sie testen können, ob zwei Objektverweise auf dieselbe Objektinstanz verweisen.

Einige gute Beispiele und Erklärungen befinden sich auch im Unterschied zwischen == und ===

Bei einem @PEEJWEEJ-Punkt führen folgende Schritte zu false

var newValue: AnyObject? = "String"
var oldValue: AnyObject? = "String"

if newValue === oldValue {
   print("true")
} else {
   print("false")
}
11
sbarow

Angenommen, Sie verwenden Comparable-Entitäten. Dies funktioniert bei allem:

func optionalsAreEqual<T: Comparable>(firstVal: T?, secondVal: T?) -> Bool{

    if let firstVal = firstVal, secondVal = secondVal {
        return firstVal == secondVal
    }
    else{
        return firstVal == nil && secondVal == nil
   }
}

Es ist nicht gerade kurz und süß, aber es ist ausdrucksstark, klar und wiederverwendbar.

11
PeejWeej

Mir hat @ Keith's -Lösung gefallen. Aber ich denke, es ist nicht in Swift 4 geschrieben, da ich es nicht mit Swift 4 Compiler kompilieren kann.

Also habe ich seinen Code hier in die Swift 4-Version konvertiert.

Denken Sie daran, wenn Sie eine höhere Version von Swift verwenden als Swift 4.1 , dann ist diese Antwort ist nicht erforderlich , da diese Funktion standardmäßig bereitgestellt wird. hier für weitere Details. 

Swift 4-Version von @ Keys Code:

infix operator ==? : ComparisonPrecedence

func ==? <T: Comparable>(lhs: T?, rhs: T?) -> Bool {
    if let lhs = lhs, let rhs = rhs {
        return lhs == rhs
    } else {
        return lhs == nil && rhs == nil
    }
}

func ==? <T: AnyObject>(lhs: T?, rhs: T?) -> Bool {
    if let lhs = lhs, let rhs = rhs {
        return lhs === rhs
    } else {
        return lhs == nil && rhs == nil
    }
}
4
Nitesh Borad

Ich definiere einen benutzerdefinierten Infix-Operator mit einer Funktion für Referenztypen und Werttypen.

func ==? <T: Comparable>(lhs: T?, rhs: T?) -> Bool {
    if let lhs = lhs, rhs = rhs {
        return lhs == rhs
    } else{ return lhs == nil && rhs == nil }
}
func ==? <T: AnyObject>(lhs: T?, rhs: T?) -> Bool {
    if let lhs = lhs, rhs = rhs {
        return lhs === rhs
    } else{ return lhs == nil && rhs == nil }
}
infix operator ==? { associativity left precedence 130 }

var aString: String? = nil
var bString: String? = nil
print(aString ==? bString) // true

aString = "test"
bString = "test"
print(aString ==? bString) // true

aString = "test2"
bString = "test"
print(aString ==? bString) // false

aString = "test"
bString = nil
print(aString ==? bString) // false

class TT {}
let x = TT()

var aClass: TT? = TT()
var bClass: TT? = TT()
print(aClass ==? bClass) // false

aClass = TT()
bClass = nil
print(aClass ==? bClass) // false

aClass = nil
bClass = nil
print(aClass ==? bClass) // true

aClass = x
bClass = x
print(aClass ==? bClass) // true
3
Keith

Sie können den ==-Operator für einen Comparable-Typ überladen

public func ==<T: SomeType>(lhs: T?, rhs: T?) -> Bool {
    switch (lhs,rhs) {
    case (.some(let lhs), .some(let rhs)):
        return lhs == rhs
    case (.none, .none):
        return true
    default:
        return false
    }
}

Oder verwenden Sie === Comparison für AnyObject, obwohl ich persönlich lieber AnyObject nicht verwenden möchte.

0
nikans