Utilisation de plusieurs let-as dans une instruction if dans Swift

144

Je déballe deux valeurs d'un dictionnaire et avant de les utiliser, je dois les convertir et tester le bon type. Voici ce que j'ai proposé:

var latitude : AnyObject! = imageDictionary["latitude"]
var longitude : AnyObject! = imageDictionary["longitude"]

if let latitudeDouble = latitude as? Double  {
   if let longitudeDouble = longitude as? Double {
       // do stuff here
   }
}

Mais je voudrais regrouper les deux si vous laissez les requêtes en un seul. Pour que ce soit quelque chose comme ça:

if let latitudeDouble = latitude as? Double, longitudeDouble = longitude as? Double {
    // do stuff here
}

Cette syntaxe ne fonctionne pas, alors je me demandais s'il y avait une belle façon de le faire.

suntoch
la source
Il peut y avoir un moyen d'utiliser une instruction switch pour faire correspondre les types aux modèles. Jetez un oeil à la documentation :
lomokat
1
duplication possible de l' utilisation de "if let ..." avec de nombreuses expressions
rickster

Réponses:

305

Mise à jour pour Swift 3:

Ce qui suit fonctionnera dans Swift 3:

if let latitudeDouble = latitude as? Double, let longitudeDouble = longitude as? Double {
    // latitudeDouble and longitudeDouble are non-optional in here
}

N'oubliez pas que si l'une des tentatives de liaison facultative échoue, le code à l'intérieur du if-letbloc ne sera pas exécuté.

Remarque: les clauses ne doivent pas toutes être des clauses «let», vous pouvez avoir n'importe quelle série de vérifications booléennes séparées par des virgules.

Par exemple:

if let latitudeDouble = latitude as? Double, importantThing == true {
    // latitudeDouble is non-optional in here and importantThing is true
}

Swift 1.2:

Apple a peut-être lu votre question, car votre code espéré se compile correctement dans Swift 1.2 (en version bêta aujourd'hui):

if let latitudeDouble = latitude as? Double, longitudeDouble = longitude as? Double {
    // do stuff here
}

Swift 1.1 et versions antérieures:

Voici la bonne nouvelle - vous pouvez tout à fait le faire. Une instruction switch sur un tuple de vos deux valeurs peut utiliser la correspondance de modèle pour les convertir toutes les deux en Doublemême temps:

var latitude: Any! = imageDictionary["latitude"]
var longitude: Any! = imageDictionary["longitude"]

switch (latitude, longitude) {
case let (lat as Double, long as Double):
    println("lat: \(lat), long: \(long)")
default:
    println("Couldn't understand latitude or longitude as Double")
}

Mise à jour: cette version du code fonctionne désormais correctement.

Nate Cook
la source
ça marche pour moi en 6.1.1, @AaronBratcher pourquoi pas à toi?
Daniel Gomez Rico
1
Dans Swift 1.2, il est désormais possible de le faire en une seule ligne: stackoverflow.com/a/28418847/1698576
smithclay
Dans votre code, vous avez 2 options en cours de déroulement. Doit-il toujours être utilisé comme ça? J'ai un code déroutant différent. if let app = UIApplication.sharedApplication().delegate as? AppDelegate, let window = app.window {...}. Le 2ème est-il let également facultatif? Je veux appdire, ce n'est plus une option. droite?
Honey
1
C'est. appn'est plus une option, mais sa windowpropriété est (son type est UIWindow?), c'est donc ce que vous déballez.
Nate Cook
7

Avec Swift 3, vous pouvez utiliser un chaînage optionnel, une instruction switch ou un modèle optionnel pour résoudre votre problème.


1. Utilisation if let(reliure optionnelle / chaînage optionnel)

Le langage de programmation Swift indique le chaînage facultatif:

Plusieurs requêtes peuvent être enchaînées et la chaîne entière échoue correctement si un lien de la chaîne est nul.

Par conséquent, dans le cas le plus simple, vous pouvez utiliser le modèle suivant pour utiliser plusieurs requêtes dans votre opération de chaînage facultative:

let dict = ["latitude": 2.0 as AnyObject?, "longitude": 10.0 as AnyObject?]
let latitude = dict["latitude"]
let longitude = dict["longitude"]

if let latitude = latitude as? Double, let longitude = longitude as? Double {
    print(latitude, longitude)
}

// prints: 2.0 10.0

2. Utilisation de tuples et de liaison de valeur dans une instruction switch

Comme alternative à un simple chaînage facultatif, l' instruction switch peut offrir une solution fine lorsqu'elle est utilisée avec des tuples et une liaison de valeur:

let dict = ["latitude": 2.0 as AnyObject?, "longitude": 10.0 as AnyObject?]
let latitude = dict["latitude"]
let longitude = dict["longitude"]

switch (latitude, longitude) {
case let (Optional.some(latitude as Double), Optional.some(longitude as Double)):
    print(latitude, longitude)
default:
    break
}

// prints: 2.0 10.0
let dict = ["latitude": 2.0 as AnyObject?, "longitude": 10.0 as AnyObject?]
let latitude = dict["latitude"]
let longitude = dict["longitude"]

switch (latitude, longitude) {
case let (latitude as Double, longitude as Double):
    print(latitude, longitude)
default:
    break
}

// prints: 2.0 10.0
let dict = ["latitude": 2.0 as AnyObject?, "longitude": 10.0 as AnyObject?]
let latitude = dict["latitude"]
let longitude = dict["longitude"]

switch (latitude as? Double, longitude as? Double) {
case let (.some(latitude), .some(longitude)):
    print(latitude, longitude)
default:
    break
}

// prints: 2.0 10.0
let dict = ["latitude": 2.0 as AnyObject?, "longitude": 10.0 as AnyObject?]
let latitude = dict["latitude"]
let longitude = dict["longitude"]

switch (latitude as? Double, longitude as? Double) {
case let (latitude?, longitude?):
    print(latitude, longitude)
default:
    break
}

// prints: 2.0 10.0

3. Utilisation de tuples avec if case(modèle facultatif)

if case( modèle facultatif ) fournit un moyen pratique de déballer les valeurs de l'énumération facultative. Vous pouvez l'utiliser avec des tuples afin d'effectuer un chaînage facultatif avec plusieurs requêtes:

let dict = ["latitude": 2.0 as AnyObject?, "longitude": 10.0 as AnyObject?]
let latitude = dict["latitude"]
let longitude = dict["longitude"]

if case let (.some(latitude as Double), .some(longitude as Double)) = (latitude, longitude) {
    print(latitude, longitude)
}

// prints: 2.0 10.0
let dict = ["latitude": 2.0 as AnyObject?, "longitude": 10.0 as AnyObject?]
let latitude = dict["latitude"]
let longitude = dict["longitude"]

if case let (latitude as Double, longitude as Double) = (latitude, longitude) {
    print(latitude, longitude)
}

// prints: 2.0 10.0
let dict = ["latitude": 2.0 as AnyObject?, "longitude": 10.0 as AnyObject?]
let latitude = dict["latitude"]
let longitude = dict["longitude"]

if case let (.some(latitude), .some(longitude)) = (latitude as? Double, longitude as? Double) {
    print(latitude, longitude)
}

// prints: 2.0 10.0
let dict = ["latitude": 2.0 as AnyObject?, "longitude": 10.0 as AnyObject?]
let latitude = dict["latitude"]
let longitude = dict["longitude"]

if case let (latitude?, longitude?) = (latitude as? Double, longitude as? Double) {
    print(latitude, longitude)
}

// prints: 2.0 10.0
Imanou Petit
la source
5

Swift 3.0

if let latitudeDouble = latitude as? Double, let longitudeDouble = longitude as? Double {
    // do stuff here
}
norbDEV
la source
4
Vous devriez suggérer une modification de la réponse acceptée, n'ajoutez pas une autre réponse de qualité inférieure.
jervine10