2016-06-03 25 views
5

Vorrei attivare la logica condizionale basata su determinate relazioni dell'interfaccia utente durante l'interazione dell'utente (in questo caso, voglio chiamare un metodo quando un utente scorre a un certo punto in a UIScrollView). Mi aspetterei la seguente riga di codice per fare questo legalmente, dal momento che è molto espressiva:Uso delle clausole "where" per produrre tipi facoltativi in ​​Aritmetica Swift

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

    reactToScrollOverlap(of: overlap) 
} 

Tuttavia, ottengo l'errore che il guard let richiede un tipo di optional. Questo è ragionevole, ma in questo caso mi aspettavo che la clausola where introdurrebbe naturalmente un optional, poiché se l'aritmetica funziona in modo errato, non c'è alcun valore corrispondente di overlap.

C'è un modo per utilizzare guard let (o, in alternativa, if let) tale che comprendeva where clausole prevedono condizioni sui risultati dell'aritmetica tra Int, CGFloat, o altri tipi primitivi/primitivo-come?

risposta

2

State facendo 3 cose in una sola espressione - dichiarazione di una variabile (costante), l'assegnazione e il controllo il suo valore

Dichiarare una variabile nelle espressioni è solitamente disapprovato, Swift in realtà non lo abilita. Con una sola eccezione: scartare gli optionals. Non si Scartare un optional quindi basta dividere l'espressione in modo corretto in una dichiarazione e un confronto:

let overlap = contentOffset.y - 220 

guard overlap > 0 else { 
    return 
} 

Un'altra opzione è quella di utilizzare il modello case let. Non ne sono un grande fan ma è probabilmente quello che vuoi:

guard case let overlap = contentOffset.y - 220 where overlap > 0 else { 
    return 
} 

print("overlap:", overlap) 
+0

Suppongo che questa sia l'alternativa più espressiva, quindi contrassegnerò questa come risposta fino a nuovo avviso (: – Quintana

+0

ripensandoci, ho contrassegnato l'altra come corretta perché anche se hai ragione e dovrei farlo probabilmente, la soluzione alternativa fornita da JAL utilizza le clausole where indicate nel titolo – Quintana

+0

@Quintana Prova la mia seconda soluzione – Sulthan

3

guard e if let vengono normalmente utilizzate solo per scartare gli optionals. Io non sono davvero entusiasta di questa soluzione, ma si potrebbe lanciare scrollView.contentOffset.y come Optional<CGFloat> per ottenere il comportamento desiderato:

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

Questa è una buona soluzione che penso arrivi a ciò che speravo fosse possibile. Non è elettrizzante, come tu dici, tuttavia, non vorrebbe controllarlo. Ma vorrei poter contrassegnare più risposte corrette. Grazie per segnalarlo. – Quintana

3
guard let value = someOptionalValue { 
} 

if let value = someOptionalValue { 
} 

Questi sono il modo in cui si associa un optional a una variabile. Se si utilizza guard let o if let che si sta utilizzando per ottenere un valore solo da tipi facoltativi.

e la clausola where verrà attivata solo quando tutti gli optionals hanno un valore che precede la clausola where.

Penso che ciò che si vuole fare è qualcosa di simile:

let delta = scrollView.contentOffset.y - 220 

if delta > 0 { 

} else { 

} 

preferirei chiarezza sulle brevità.

Edit:

Ecco un modo migliore per farlo penso:

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

Ha senso.Non sta ancora esprimendo ciò che vorrei - poiché mi interessa solo l'offset in cui è maggiore di 220, preferirei avere un valore 'nil' piuttosto che uno 'invalid'; nel senso che "nessun delta potrebbe essere creato". tuttavia questo funziona, grazie. – Quintana

+0

Controlla la mia modifica in quel caso! –