是否有可能创建对结构数组元素的引用?

Che*_*eng 3 struct reference ios swift

给定一个Arraystruct

    import Foundation
    
    struct Card {
        var flag: String = ""
    }
    
    var cards = Array<Card>()
    cards.append(Card())
Run Code Online (Sandbox Code Playgroud)

以下操作不会修改原始数组元素

    // A copy is created.
    var cardCopy = cards[0]
    
    // Will NOT modify cards[0] 
    cardCopy.flag = "modify0"
    
    print(cards[0].flag)
Run Code Online (Sandbox Code Playgroud)

以下操作将修改原始数组元素

    // We can modify cards[0] by
    cards[0].flag = "modify"

    print(cards[0].flag)
Run Code Online (Sandbox Code Playgroud)

然而,它在某种意义上并不高效,我们每次都需要执行索引访问。想象

    cards[0].flag0 = "modify"
    cards[0].flag1 = "modify"
    cards[0].flag2 = "modify"
    cards[0].flag3 = "modify"
    ...
Run Code Online (Sandbox Code Playgroud)

有没有办法,我们可以创建对结构数组元素的引用?这样我们就可以写

// How to create a reference to cards[0]?
var cardReference = ...
Run Code Online (Sandbox Code Playgroud)
// How to create a reference to cards[0]?
var cardReference = ...
Run Code Online (Sandbox Code Playgroud)

一种可能性是替换structclass. 但是,在此之前,我想探索其他替代方案。

gch*_*ita 7

您可以使用函数进行更改并通过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])
Run Code Online (Sandbox Code Playgroud)

或者通过在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"
}
Run Code Online (Sandbox Code Playgroud)

更新:为了使第二种方法更具可重用性,您可以定义如下协议:

protocol Updatable {
    mutating func update(block: (inout Self) -> Void)
}

extension Updatable {
    mutating func update(block: (inout Self) -> Void) {
        block(&self)
    }
}
Run Code Online (Sandbox Code Playgroud)

并使Card结构符合它:

struct Card: Updatable {
    var flag0: String = ""
    var flag1: String = ""
    var flag2: String = ""
    var flag3: String = ""
}
Run Code Online (Sandbox Code Playgroud)

然后你可以像上面一样使用它。