Est-il jamais possible de créer une référence à l'élément du tableau de la structure?
Étant donné un Array
avecstruct
import Foundation
struct Card {
var flag: String = ""
}
var cards = Array<Card>()
cards.append(Card())
L'opération suivante ne modifiera PAS l'élément d'origine du tableau
// A copy is created.
var cardCopy = cards[0]
// Will NOT modify cards[0]
cardCopy.flag = "modify0"
print(cards[0].flag)
L'opération suivante modifiera l'élément original du tableau
// We can modify cards[0] by
cards[0].flag = "modify"
print(cards[0].flag)
Cependant, ce n'est pas efficace dans le sens où nous devons effectuer un accès d'indexation à chaque fois. Imaginer
cards[0].flag0 = "modify"
cards[0].flag1 = "modify"
cards[0].flag2 = "modify"
cards[0].flag3 = "modify"
...
Y a-t-il un moyen, nous pouvons créer une référence à l'élément du tableau de la structure? Pour que nous puissions écrire
// How to create a reference to cards[0]?
var cardReference = ...
cardReference.flag0 = "modify"
cardReference.flag1 = "modify"
cardReference.flag2 = "modify"
cardReference.flag3 = "modify"
...
L'une des possibilités est de remplacer struct
par class
. Mais j'aimerais explorer une autre alternative, avant de le faire.
Réponses
Vous pouvez y parvenir en utilisant une fonction pour apporter vos modifications et passer la Card
structure par référence comme ceci:
func update(card: inout Card) {
card.flag0 = "modify"
card.flag1 = "modify"
card.flag2 = "modify"
card.flag3 = "modify"
}
var cards = Array<Card>()
cards.append(Card())
update(card: &cards[0])
ou encore mieux en utilisant une fonction de mutation dans le Card
type et en passant comme fermeture vos changements comme ça:
struct Card {
var flag0: String = ""
var flag1: String = ""
var flag2: String = ""
var flag3: String = ""
mutating func update(block: (inout Card) -> Void) {
block(&self)
}
}
var cards = Array<Card>()
cards.append(Card())
cards[0].update {
$0.flag0 = "modify" $0.flag1 = "modify"
$0.flag2 = "modify" $0.flag3 = "modify"
}
Mise à jour : pour rendre la deuxième approche encore plus réutilisable, vous pouvez définir un protocole comme celui-ci:
protocol Updatable {
mutating func update(block: (inout Self) -> Void)
}
extension Updatable {
mutating func update(block: (inout Self) -> Void) {
block(&self)
}
}
et rendez Card
struct conforme à lui:
struct Card: Updatable {
var flag0: String = ""
var flag1: String = ""
var flag2: String = ""
var flag3: String = ""
}
Ensuite, vous pouvez l'utiliser comme ci-dessus.
C'est le comportement attendu, car Array
est a struct
et struct
s sont des types valeur.
Ce dont vous avez besoin est un comportement de type référence, vous devez donc convertir votre fichier struct
en class
.
Une autre solution pour modifier plusieurs propriétés d'un type valeur en une seule fois consiste à créer une mutating
fonction qui fait cela et à l'appeler sur l'élément de tableau.
struct Card {
var flag: String = ""
var flag2 = ""
mutating func update(flag: String, flag2: String) {
self.flag = flag
self.flag2 = flag2
}
}
var cards = [Card(flag: "a", flag2: "b")]
cards[0].update(flag: "b", flag2: "c")