È mai possibile creare un riferimento a un elemento di array di struct?
Dato un Array
construct
import Foundation
struct Card {
var flag: String = ""
}
var cards = Array<Card>()
cards.append(Card())
La seguente operazione NON modificherà l'elemento dell'array originale
// A copy is created.
var cardCopy = cards[0]
// Will NOT modify cards[0]
cardCopy.flag = "modify0"
print(cards[0].flag)
La seguente operazione modificherà l'elemento dell'array originale
// We can modify cards[0] by
cards[0].flag = "modify"
print(cards[0].flag)
Tuttavia, non è efficiente nel senso, dobbiamo eseguire ogni volta l'accesso all'indicizzazione. Immaginare
cards[0].flag0 = "modify"
cards[0].flag1 = "modify"
cards[0].flag2 = "modify"
cards[0].flag3 = "modify"
...
C'è un modo, possiamo creare un riferimento all'elemento dell'array di struct? In modo che possiamo scrivere
// How to create a reference to cards[0]?
var cardReference = ...
cardReference.flag0 = "modify"
cardReference.flag1 = "modify"
cardReference.flag2 = "modify"
cardReference.flag3 = "modify"
...
Una delle possibilità è sostituire struct
con class
. Ma vorrei esplorare altre alternative, prima di farlo.
Risposte
Puoi ottenerlo usando una funzione per apportare le tue modifiche e passare la Card
struttura per riferimento in questo modo:
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 ancora meglio usando una funzione mutante nel Card
tipo e passa come chiusura le tue modifiche in questo modo:
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"
}
Aggiornamento : per rendere il secondo approccio ancora più riutilizzabile, puoi definire un protocollo come questo:
protocol Updatable {
mutating func update(block: (inout Self) -> Void)
}
extension Updatable {
mutating func update(block: (inout Self) -> Void) {
block(&self)
}
}
e rendi la Card
struttura conforme ad essa:
struct Card: Updatable {
var flag0: String = ""
var flag1: String = ""
var flag2: String = ""
var flag3: String = ""
}
Quindi puoi usarlo proprio come sopra.
Questo è il comportamento previsto, poiché Array
è a struct
e struct
s sono tipi di valore.
Ciò di cui hai bisogno è il comportamento del tipo di riferimento, quindi dovresti convertire il tuo struct
in un file class
.
Un'altra soluzione per modificare diverse proprietà di un tipo di valore in una volta è creare una mutating
funzione che lo faccia e chiamarla sull'elemento dell'array.
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")