2017-09-02 2 views
0

Je sais à Swift que je peux faire une simple déclaration de commutateur Swift pour comparer les valeurs calculées avec une seule variable:déclaration Swift 4 commutateur comparant plusieurs valeurs, utilisant plus ou moins de

let distanceTravelled = -145.1 
switch distanceTravelled { 
case _ where distanceTravelled < 15: 
    print("You travelled the right distance") 
default: 
    print("Sad face") 
} 

Mais je veux être capable de mettre en place une matrice de comparaisons en utilisant tuples, quelque chose comme ceci:

let distanceTravelled = -145.1, 
    origin = 2 

switch (origin, distanceTravelled) { 
case (2, _ where distanceTravelled < 15): 
    print("You travelled the right distance") 
default: 
    print("Sad face") 
} 

Mais cela ne compile pas, se plaignant que expected ',' separator et expected expression in list of expressions.

De toute évidence, cela est syntaxiquement incorrect, mais cela ne devrait-il pas fonctionner étant donné que cela fonctionne?

switch (2, -145.1) { 
case (2, _): 
    print("You travelled the right distance") 
default: 
    print("Sad face") 
} 

Répondre

2

Aha! Trouvé la réponse dans le bon vieux 'Swift docs. Je ne pensais pas à cela en termes de tuple.

switch (origin, distanceTravelled) { 
case let (_, d) where d < 15: 
    print("You travelled the right distance") 
default: 
    print("Sad face") 
} 

Pour mon cas réel d'utilisation, cela a un peu plus étrange parce que je comparais une propriété enum pour origine, mais ça a marché:

let absOriginDistanceFromDefault = abs(defaultDividerPosition - viewDividerOrigin) 

switch (splitViewOrigin, distanceTravelled) { 
case let (.defaultPosition, d) where d < -100: 
    return .shouldMoveToTopView 
case let (.defaultPosition, d) where d > 100: 
    return .shouldMoveToBottomView 
case (.topView, _) where currentDividerPosition - defaultDividerPosition < -100: 
    return .shouldMoveToBottomView 
case (.topView, _) where abs(distanceTravelled) > absOriginDistanceFromDefault * 0.5 && currentDividerPosition < self.view.bounds.height: 
    return .shouldMoveToDefaultPosition 
case (.bottomView, _) where currentDividerPosition - defaultDividerPosition > 100: 
    return .shouldMoveToTopView 
case (.bottomView, _) where abs(distanceTravelled) > absOriginDistanceFromDefault * 0.3 && currentDividerPosition > 0: 
    return .shouldMoveToDefaultPosition 
default: 
    return .shouldReturnToOrigin 
} 

Et assez curieusement, en simplifier encore, il s'avère que je n'ai même pas besoin de déclarer les variables dans les deux premiers contrôles du tout:

let absOriginDistanceFromDefault = abs(defaultDividerPosition - viewDividerOrigin) 

switch (splitViewOrigin, distanceTravelled) { 
case (.defaultPosition, _) where distanceTravelled < -100, 
    (.bottomView, _) where currentDividerPosition - defaultDividerPosition > 100: 
    return .shouldMoveToTopView 
case (.defaultPosition, _) where distanceTravelled > 100, 
    (.topView, _) where currentDividerPosition - defaultDividerPosition < -100: 
    return .shouldMoveToBottomView 
case (.topView, _) where abs(distanceTravelled) > absOriginDistanceFromDefault * 0.5 && currentDividerPosition < maxHeight, 
    (.bottomView, _) where abs(distanceTravelled) > absOriginDistanceFromDefault * 0.3 && currentDividerPosition > 0: 
    return .shouldMoveToDefaultPosition 
default: 
    return .shouldReturnToOrigin 
}