É possível criar uma referência ao elemento da matriz de estrutura?
Dado um Array
comstruct
import Foundation
struct Card {
var flag: String = ""
}
var cards = Array<Card>()
cards.append(Card())
A operação a seguir NÃO modificará o elemento original da matriz
// A copy is created.
var cardCopy = cards[0]
// Will NOT modify cards[0]
cardCopy.flag = "modify0"
print(cards[0].flag)
A seguinte operação irá modificar o elemento original da matriz
// We can modify cards[0] by
cards[0].flag = "modify"
print(cards[0].flag)
No entanto, não é eficiente no sentido de que precisamos executar o acesso de indexação a cada vez. Imagine
cards[0].flag0 = "modify"
cards[0].flag1 = "modify"
cards[0].flag2 = "modify"
cards[0].flag3 = "modify"
...
Existe uma maneira, podemos criar referência ao elemento do array de struct? Para que possamos escrever
// How to create a reference to cards[0]?
var cardReference = ...
cardReference.flag0 = "modify"
cardReference.flag1 = "modify"
cardReference.flag2 = "modify"
cardReference.flag3 = "modify"
...
Uma das possibilidades é substituir struct
por class
. Mas, eu gostaria de explorar outra alternativa, antes de fazer isso.
Respostas
Você pode conseguir isso usando uma função para fazer suas alterações e passar a Card
estrutura por referência desta forma:
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 melhor ainda, usando uma função mutante no Card
tipo e passar como um encerramento suas alterações como esta:
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"
}
Atualização : para tornar a segunda abordagem ainda mais reutilizável, você pode definir um protocolo como este:
protocol Updatable {
mutating func update(block: (inout Self) -> Void)
}
extension Updatable {
mutating func update(block: (inout Self) -> Void) {
block(&self)
}
}
e fazer com que a Card
estrutura esteja em conformidade com ela:
struct Card: Updatable {
var flag0: String = ""
var flag1: String = ""
var flag2: String = ""
var flag3: String = ""
}
Então você pode usá-lo como acima.
Este é o comportamento esperado, uma vez que Array
a struct
e struct
s são tipos de valor.
O que você precisa é um comportamento de tipo de referência, portanto, você deve converter seu struct
para um class
.
Outra solução para modificar várias propriedades de um tipo de valor de uma vez é criar uma mutating
função que faça isso e chamar isso no elemento da 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")