Yapı dizisi elemanına bir başvuru yaratmak mümkün müdür?

Aug 19 2020

Bir göz önüne alındığında Arrayilestruct

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

Aşağıdaki işlem orijinal dizi elemanını DEĞİŞTİRMEZ

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

Aşağıdaki işlem orijinal dizi elemanını değiştirecek

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

    print(cards[0].flag)

Ancak, bu anlamda verimli değil, her seferinde indeksleme erişimi gerçekleştirmemiz gerekiyor. Hayal etmek

    cards[0].flag0 = "modify"
    cards[0].flag1 = "modify"
    cards[0].flag2 = "modify"
    cards[0].flag3 = "modify"
    ...

Yapı dizisi elemanına referans oluşturmanın bir yolu var mı? Böylece yazabiliriz

// How to create a reference to cards[0]?
var cardReference = ...
    cardReference.flag0 = "modify"
    cardReference.flag1 = "modify"
    cardReference.flag2 = "modify"
    cardReference.flag3 = "modify"
    ...

Olasılıklardan biri değiştirmektir structile class. Ama bunu yapmadan önce başka bir alternatif keşfetmek isterim.

Yanıtlar

7 gcharita Aug 19 2020 at 11:25

Değişikliklerinizi yapmak ve Cardyapıyı aşağıdaki gibi referansla geçmek için bir işlev kullanarak bunu başarabilirsiniz :

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])

hatta daha da iyisi, Cardtipte bir mutasyon işlevi kullanarak ve değişikliklerinizi şu şekilde tamamlayarak geçebilir:

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"
}

Güncelleme : İkinci yaklaşımı daha da tekrar kullanılabilir hale getirmek için aşağıdaki gibi bir protokol tanımlayabilirsiniz:

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

extension Updatable {
    mutating func update(block: (inout Self) -> Void) {
        block(&self)
    }
}

ve Cardyapıyı buna uygun hale getirin:

struct Card: Updatable {
    var flag0: String = ""
    var flag1: String = ""
    var flag2: String = ""
    var flag3: String = ""
}

O zaman yukarıdaki gibi kullanabilirsiniz.

DávidPásztor Aug 19 2020 at 11:16

Bu beklenen davranıştır, çünkü Arraya structve structs değer türleridir.

İstemiyorsun, mutfakta annene dönüştürmek gerekir böylece Ne gerek, başvuru türü davranıştır structa class.

Bir değer türünün çeşitli özelliklerini tek seferde değiştirmek için başka bir çözüm mutating, bunu yapan bir işlev oluşturmak ve bunu dizi öğesinde çağırmaktır.

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")