Si vous voulez vraiment ce comportement, cela sent comme si vous vouliez un dictionnaire au lieu d'un tableau. Les dictionnaires reviennent nil
lors de l'accès aux clés manquantes, ce qui est logique car il est beaucoup plus difficile de savoir si une clé est présente dans un dictionnaire car ces clés peuvent être n'importe quoi, où dans un tableau la clé doit être dans une plage de: 0
à count
. Et il est incroyablement courant d'itérer sur cette plage, où vous pouvez être absolument sûr d' avoir une valeur réelle à chaque itération d'une boucle.
Je pense que la raison pour laquelle cela ne fonctionne pas de cette façon est un choix de conception fait par les développeurs de Swift. Prenez votre exemple:
var fruits: [String] = ["Apple", "Banana", "Coconut"]
var str: String = "I ate a \( fruits[0] )"
Si vous savez déjà que l'index existe, comme vous le faites dans la plupart des cas où vous utilisez un tableau, ce code est parfait. Cependant, si l'accès à un indice peut éventuellement renvoyer, nil
vous avez modifié le type de retour de Array
la subscript
méthode de en option. Cela change votre code en:
var fruits: [String] = ["Apple", "Banana", "Coconut"]
var str: String = "I ate a \( fruits[0]! )"
// ^ Added
Ce qui signifie que vous devrez déballer une option à chaque fois que vous itérerez dans un tableau, ou que vous ferez quoi que ce soit d'autre avec un index connu, simplement parce que vous pourriez rarement accéder à un index hors limites. Les concepteurs de Swift ont opté pour moins de déballage des options, au détriment d'une exception d'exécution lors de l'accès aux index hors limites. Et un plantage est préférable à une erreur logique causée par un résultat nil
inattendu quelque part dans vos données.
Et je suis d'accord avec eux. Vous ne modifierez donc pas l' Array
implémentation par défaut, car vous casseriez tout le code qui attend des valeurs non facultatives des tableaux.
Au lieu de cela, vous pouvez sous Array
-classer et remplacer subscript
pour renvoyer une option. Ou, plus concrètement, vous pouvez étendre Array
avec une méthode non-indice qui fait cela.
extension Array {
// Safely lookup an index that might be out of bounds,
// returning nil if it does not exist
func get(index: Int) -> T? {
if 0 <= index && index < count {
return self[index]
} else {
return nil
}
}
}
var fruits: [String] = ["Apple", "Banana", "Coconut"]
if let fruit = fruits.get(1) {
print("I ate a \( fruit )")
// I ate a Banana
}
if let fruit = fruits.get(3) {
print("I ate a \( fruit )")
// never runs, get returned nil
}
Mise à jour Swift 3
func get(index: Int) ->
T?
doit être remplacé par func get(index: Int) ->
Element?