2017-08-04 3 views
0

Je veux mettre rapidement 3 do-catch dans une fonction plutôt que de l'écrire constamment partout où j'en ai besoin; à l'intérieur de cette fonction, je souhaite retourner un tuple avec un booléen, et une erreur facultative.Swift Comment retourner un tuple à partir d'un do où la liaison conditionnelle doit avoir un type optionnel?

Je suis en train de retourner un tuple de la fonction et de gérer le résultat dans mon XCTest

Cependant, je reçois une erreur disant:

Initializer pour condition de liaison doit être de type en option, non ' (Bool, Error?) '(Alias' (Bool, Facultatif) ')

Ma fonction est la suivante;

public static func isValidPurchase(train: Train, player: Player) -> (Bool, Error?) { 
    do { 
     let result = try train.canBePurchased(by: player) 
     return (result, nil) 
    } catch let error { 
     return (false, error) 
    } 
} 

Mon code canBePurchased est un peu long, mais il va comme ceci:

func canBePurchased(by player: Player) throws -> Bool { 

     if (!self.isUnlocked) { 
      throw ErrorCode.trainIsNotUnlocked(train: self) 
     } 

    // other if-statements and throws go here 
} 

Et dans mon XCTest je l'appelle en tant que tel:

if let result = TrainAPI.isValidPurchase(train: firstTrain, player: firstPlayer) as! (Bool, Error?) { 

} 

J'ai essayé de Forcer la distribution:

if let result: (Bool, Error?) ...

mais cela ne rétrograde l'erreur de compilation à un avertissement.

Le module complémentaire affiche l'erreur comme indiqué ci-dessus.

Qu'est-ce que je fais mal en termes de Initializer for conditional binding must have Optional type et comment l'éviter?

Merci

Répondre

1

Le type de retour de isValidPurchase(train:player) est (Bool, Error?), ce qui est une option (il est un tuple où le 2ème membre se trouve être une option). Par conséquent, il est inutile d'utiliser la liaison facultative lors de la capture du retour d'un appel à isValidPurchase(train:player). Vous attribuez simplement la valeur de retour et d'étudier son contenu (erreur possible, etc.) à partir de là:

// e.g. using explicitly separate tuple members 
let (result, error) = TrainAPI 
    .isValidPurchase(train: firstTrain, player: firstPlayer) 

if let error = error { /* you have an error */ } 
else { /* no error, proceed with 'result' */ } 

Ou, étudier le retour en utilisant une instruction switch:

// result is a tuple of type (Bool, Error?) 
let result = TrainAPI 
     .isValidPurchase(train: firstTrain, player: firstPlayer) 

switch result { 
    case (_, let error?): print("An error occured!") 
    case (let result, _): print("Result = \(result)") 
} 
+0

Compris. Je vais faire le changement et merci pour l'aide – zardon

1

Utilisez simplement le moulage en option plutôt que la coulée sous pression. L'utilisation du résultat de la distribution forcée aurait une valeur non facultative même si elle était utilisée sans l'instruction if let.

if let result = TrainAPI.isValidPurchase(train: firstTrain, player: firstPlayer) as? (Bool, Error?) { 

} 
+0

Oh ok, merci beaucoup – zardon

+0

Ceci effectuera une tentative de conversion de '(Bool, Error?)' en '(Bool, Error?)', c'est-à-dire une tentative de conversion d'un type en lui-même, qui réussira toujours (et si vous l'essayez dans votre projet, le compilateur devrait vous avertir que cette affaire réussit toujours). Il s'agit donc simplement d'un moyen détourné d'assigner une instance à une propriété ('result') en l'empaquetant d'abord dans le' .some (...) 'd'un optionnel, puis en le déballant immédiatement sur une valeur concrète. – dfri