2016-06-03 17 views
5

Chciałbym wyzwalać logikę warunkową opartą na pewnych relacjach UI podczas interakcji użytkownika (w tym przypadku chcę wywołać metodę, gdy użytkownik przewinie do określonego punktu w a UIScrollView). Spodziewam się następujący wiersz kodu, aby to zrobić zgodnie z prawem, ponieważ jest to dość wyrazisty:Używanie klauzul "where" do tworzenia typów opcjonalnych w arytmetykach Swift

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

    reactToScrollOverlap(of: overlap) 
} 

Jednakże pojawia się błąd, że guard let wymaga opcjonalnego typu. Jest to uzasadnione, ale spodziewałem się w tym przypadku, że klauzula where w naturalny sposób wprowadzi opcjonalne, ponieważ jeśli arytmetyka się nie powiedzie, nie ma zgodnej wartości overlap.

Czy istnieje sposób na wykorzystanie guard let (lub, alternatywnie, if let), tak że zawarte where klauzule przewidują warunki na wynikach arytmetycznych między Int, CGFloat lub innych prymitywnych/prymitywny podobnych typów?

Odpowiedz

2

Robicie 3 rzeczy w jednym wyrażeniu - deklarując zmienną (stała), przypisując go i sprawdzanie jego wartość.

Deklarowanie zmiennej w wyrażeniach jest zwykle źle na widoku, Swift tak naprawdę jej nie włącza. Z jednym wyjątkiem - rozpakowanie opcji. Nie jesteś rozpakowaniu opcjonalny tak po prostu podzielić wyraz prawidłowo w deklaracji oraz porównania:

let overlap = contentOffset.y - 220 

guard overlap > 0 else { 
    return 
} 

Inną opcją jest użycie wzorca case let. Nie jestem wielkim fanem tego, ale prawdopodobnie to, czego chcesz:

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

print("overlap:", overlap) 
+0

Przypuszczam, że jest to najbardziej ekspresywna alternatywa, więc zaznaczę to jako odpowiedź do następnego powiadomienia (: – Quintana

+0

po drugiej myśli, zaznaczam drugą odpowiedź jako poprawną, ponieważ chociaż masz rację i powinienem prawdopodobnie to zrobić zamiast tego, obejście udostępnione przez JAL stosuje klauzule wskazane w tytule: – Quintana

+0

@Quintana Wypróbuj moje drugie rozwiązanie – Sulthan

3

guard i if let są zwykle używane tylko do odwijania opcji. Nie jestem naprawdę zadowoleni z tego rozwiązania, ale można rzucić scrollView.contentOffset.y jako Optional<CGFloat>, aby uzyskać żądane zachowanie:

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

To jest dobre obejście, które moim zdaniem pozwala uzyskać to, na co miałem nadzieję. Nie jest to ekscytujące, jak mówisz - nie chciałbym tego sprawdzać. Ale chciałbym zaznaczyć kilka poprawnych odpowiedzi. Dziękuję za wskazanie. – Quintana

3
guard let value = someOptionalValue { 
} 

if let value = someOptionalValue { 
} 

Są to sposób, w jaki sposób powiązać ewentualne, do zmiennej. Jeśli używasz guard let lub if let, uzyskujesz wartość tylko z typów opcjonalnych.

i gdzie klauzula zostanie uruchomiona tylko wtedy, gdy wszystkie opcje mają wartość, która poprzedza klauzulę where.

myślę, co chcesz zrobić, to coś takiego:

let delta = scrollView.contentOffset.y - 220 

if delta > 0 { 

} else { 

} 

wolałbym jasności ponad zwięzłości.

Edit:

Tutaj jest lepszy sposób to zrobić myślę:

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

Ma sens.Nadal nie całkiem wyrażam to, co chciałbym - ponieważ interesuję się tylko offsetem, w którym jest większy niż 220, wolałbym mieć wartość 'nil' zamiast" nieważną "; w tym sensie, że "nie można stworzyć delty". to jednak działa, dziękuję. – Quintana

+0

Sprawdź moją edycję w takim przypadku! –

Powiązane problemy