2016-06-03 4 views
5

Ich möchte bedingte Logik basierend auf bestimmten UI-Beziehungen während Benutzerinteraktion auslösen (in diesem Fall möchte ich eine Methode aufrufen, wenn ein Benutzer zu einem bestimmten Punkt scrollt) a UIScrollView). Ich würde die folgende Zeile Code erwarten, dass dies rechtlich zu tun, da es sehr ausdrucksvoll ist:Verwenden von "Where" -Klauseln, um optionale Typen in Swift Arithmetik zu erzeugen

func scrollViewDidScroll(scrollView: UIScrollView) { 
    guard let overlap = scrollView.contentOffset.y - 220 where overlap > 0 else { 
     return 
    } 

    reactToScrollOverlap(of: overlap) 
} 

Allerdings habe ich den Fehler, dass die guard let eine optionale Art erfordert. Das ist vernünftig, aber ich habe in diesem Fall erwartet, dass die where Klausel natürlich ein optionales einführen würde, da, wenn die Arithmetik falsch funktioniert, es keinen übereinstimmenden Wert von overlap gibt.

Gibt es eine Möglichkeit guard let zu verwenden (oder alternativ if let) solche, die enthielten where Klauseln Bedingungen über die Ergebnisse der Arithmetik vor, zwischen Int, CGFloat oder anderen primitiven/primitiven artigen Typen?

Antwort

2

Sie machen 3 Dinge in einem Ausdruck - eine Variable deklarieren (konstant), ist es die Zuweisung und Überprüfung dessen Wert.

Das Deklarieren einer Variablen in Ausdrücken ist normalerweise verpönt, Swift aktiviert es nicht wirklich. Mit einer Ausnahme - Auspacken von Optionals. Sie sind Abwickeln keine optional so aufgeteilt nur den Ausdruck korrekt in eine Erklärung und ein Vergleich:

let overlap = contentOffset.y - 220 

guard overlap > 0 else { 
    return 
} 

Eine weitere Option ist das case let Muster zu verwenden. Ich bin kein großer Fan davon, aber es ist wahrscheinlich, was Sie wollen:

+0

ich nehme an, dass dies die ausdrucksvollste Alternative ist, also werde ich das bis auf weiteres als Antwort markieren (: – Quintana

+0

auf den zweiten Gedanken, ich habe die andere Antwort als richtig markiert, obwohl du recht hast und ich sollte das wahrscheinlich tun, die von JAL zur Verfügung gestellte Problemumgehung verwendet where-Klauseln wie im Titel angegeben – Quintana

+0

@Quintana Try meine zweite Lösung – Sulthan

3

guard und if let Anweisungen werden normalerweise nur zum Auspacken von Optionen verwendet. Ich bin wirklich nicht mit dieser Lösung begeistert, aber Sie scrollView.contentOffset.y als Optional<CGFloat> werfen könnte das Verhalten, das Sie erhalten möchten:

guard let overlap = scrollView.contentOffset.y - 220 as CGFloat? where overlap > 0 else { 
    return 
} 
+0

Dies ist eine gute Problemumgehung, die ich denke, was ich hoffte, ist möglich. Es ist nicht aufregend, wie du aber sagst - ich würde es nicht einchecken wollen. Aber ich wünschte, ich könnte mehrere richtige Antworten markieren. Danke, dass du es aufgezeigt hast. – Quintana

3
guard let value = someOptionalValue { 
} 

if let value = someOptionalValue { 
} 

Dies sind die Art und Weise sind, wie Sie eine optionals an eine Variable binden. Wenn Sie guard let oder if let verwenden, verwenden Sie nur einen Wert von optionalen Typen.

und where-Klausel wird nur ausgelöst, wenn alle Optionals einen Wert haben, der der where-Klausel vorausgeht.

denke ich, was wollen Sie so etwas wie dies zu tun ist:

let delta = scrollView.contentOffset.y - 220 

if delta > 0 { 

} else { 

} 

würde ich Klarheit über Kürze bevorzugen.

Edit:

Hier ist ein besserer Weg, es zu tun Ich denke:

let yOffset  = scrollView.contentOffset.y 
let newOffset:Int? = yOffset > 220 ? yOffset : nil 
+0

Macht Sinn.Es drückt immer noch nicht ganz aus, was ich möchte - da ich mich nur mit dem Offset beschäftige, bei dem es größer als 220 ist, würde ich lieber einen "Null" -Wert als einen "ungültigen" Wert haben; in dem Sinne, dass "kein Delta geschaffen werden könnte". aber das funktioniert, danke. – Quintana

+0

Überprüfen Sie meine Bearbeitung in diesem Fall! –