¿Es alguna vez posible crear una referencia a un elemento de una matriz de estructura?
Dado un Array
construct
import Foundation
struct Card {
var flag: String = ""
}
var cards = Array<Card>()
cards.append(Card())
La siguiente operación NO modificará el elemento de matriz original
// A copy is created.
var cardCopy = cards[0]
// Will NOT modify cards[0]
cardCopy.flag = "modify0"
print(cards[0].flag)
La siguiente operación modificará el elemento de matriz original
// We can modify cards[0] by
cards[0].flag = "modify"
print(cards[0].flag)
Sin embargo, no es eficiente en el sentido de que necesitamos realizar un acceso de indexación cada vez. Imagina
cards[0].flag0 = "modify"
cards[0].flag1 = "modify"
cards[0].flag2 = "modify"
cards[0].flag3 = "modify"
...
¿Hay alguna manera de que podamos crear una referencia al elemento de la matriz de la estructura? Para que podamos escribir
// How to create a reference to cards[0]?
var cardReference = ...
cardReference.flag0 = "modify"
cardReference.flag1 = "modify"
cardReference.flag2 = "modify"
cardReference.flag3 = "modify"
...
Una de las posibilidades es reemplazar struct
con class
. Pero me gustaría explorar otras alternativas antes de hacerlo.
Respuestas
Puede lograrlo usando una función para realizar sus cambios y pasar la Card
estructura por referencia como esta:
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])
o incluso mejor mediante el uso de una función mutante en el Card
tipo y pasar como cierre sus cambios de esa manera:
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"
}
Actualización : para que el segundo enfoque sea aún más reutilizable, puede definir un protocolo como este:
protocol Updatable {
mutating func update(block: (inout Self) -> Void)
}
extension Updatable {
mutating func update(block: (inout Self) -> Void) {
block(&self)
}
}
y hacer que la Card
estructura se ajuste a ella:
struct Card: Updatable {
var flag0: String = ""
var flag1: String = ""
var flag2: String = ""
var flag3: String = ""
}
Entonces puedes usarlo como arriba.
Este es el comportamiento esperado, ya Array
que a struct
y struct
s son tipos de valor.
Lo que necesita es el comportamiento del tipo de referencia, por lo que debe convertir su struct
a class
.
Otra solución para modificar varias propiedades de un tipo de valor de una vez es crear una mutating
función que haga eso y llamarla en el elemento de la matriz.
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")