Можно ли когда-нибудь создать ссылку на элемент массива структуры?
Учитывая Array
сstruct
import Foundation
struct Card {
var flag: String = ""
}
var cards = Array<Card>()
cards.append(Card())
Следующая операция НЕ изменит исходный элемент массива
// A copy is created.
var cardCopy = cards[0]
// Will NOT modify cards[0]
cardCopy.flag = "modify0"
print(cards[0].flag)
Следующая операция изменит исходный элемент массива
// We can modify cards[0] by
cards[0].flag = "modify"
print(cards[0].flag)
Однако это неэффективно в том смысле, что нам нужно каждый раз выполнять доступ к индексации. Представить
cards[0].flag0 = "modify"
cards[0].flag1 = "modify"
cards[0].flag2 = "modify"
cards[0].flag3 = "modify"
...
Есть ли способ создать ссылку на элемент массива структуры? Чтобы мы могли написать
// How to create a reference to cards[0]?
var cardReference = ...
cardReference.flag0 = "modify"
cardReference.flag1 = "modify"
cardReference.flag2 = "modify"
cardReference.flag3 = "modify"
...
Одна из возможностей - заменить struct
на class
. Но, прежде чем делать это, я хотел бы изучить другую альтернативу.
Ответы
Вы можете добиться этого, используя функцию для внесения изменений и передачи Card
структуры по ссылке следующим образом:
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])
или даже лучше, используя функцию мутации в Card
типе и передавая в качестве закрытия свои изменения следующим образом:
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"
}
Обновление : чтобы сделать второй подход еще более пригодным для повторного использования, вы можете определить такой протокол:
protocol Updatable {
mutating func update(block: (inout Self) -> Void)
}
extension Updatable {
mutating func update(block: (inout Self) -> Void) {
block(&self)
}
}
и сделайте Card
структуру соответствующей ему:
struct Card: Updatable {
var flag0: String = ""
var flag1: String = ""
var flag2: String = ""
var flag3: String = ""
}
Затем вы можете использовать его, как указано выше.
Это ожидаемое поведение, поскольку Array
is a struct
и struct
s являются типами значений.
Что вам нужно, так это поведение ссылочного типа, поэтому вам следует преобразовать struct
его в class
.
Еще одно решение для изменения нескольких свойств типа значения за один раз - создать mutating
функцию, которая делает это и вызывает ее в элементе массива.
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")