Swift 中按值传递与按引用传递的问题?

Issue with pass by value vs pass by reference in Swift?

我是 Swift 的新手,但不是 iOS 开发人员的新手。我有一个问题,我认为是由价值传递引起的。

下面的代码在 VC 中并且在点击每个按钮时工作正常,即每个按钮都会更改背景以显示它是否被选中。

    button.isSelected = card.isChosen // button is selected when the card is chosen
    if button.isSelected {
       button.setBackgroundColor(color: UIColor.darkGray, forState: UIControlState.selected)
    }

我在游戏逻辑中遇到问题,这是一个结构。 Struct 包含一个 Card 类型的数组,它实际上只是一副纸牌并映射回 UIButtons。当触摸 VC 中的卡片(UIButton)时,它会调用 Struct 中的方法(chooseCard)。除其他事项外,如果通过设置 card.isSelected = !card.isSelected 选择卡片,此操作将切换并映射回 UI 以指示是否选择了卡片。到目前为止一切正常。

When 3 cards have been selected, it calls some match logic, which is currently just stubbed out.如果没有匹配项,则每张卡片 .isSelected 都设置为 false,这样在 UI 中这些卡片将不再显示为已选中。这是行不通的,我不明白为什么。我的直觉是我在处理按值传递的方式上做错了,因为逻辑对象是一个结构。在选择了 3 张卡并且它们不匹配后(它们不会因为它只是存根),每个 card.isSelected 应该设置回 false,但它们仍然显示在 UI 中被选中。我在 VC 中设置了一个断点,它显示 card.isSelected 仍设置为 true。 VC 有一个 setGame 属性 可以访问卡片数组。这是相关代码...任何帮助表示赞赏!

    struct SetGame {

    private(set) var cards = [Card]()
    mutating public func chooseCard(at index: Int) {

        //TODO: Assertion here for index being < cards.count
        print("chooseCard(at index: \(index)")
        cards[index].isChosen = !cards[index].isChosen // toggle isChosen when card is selected

        if !cards[index].isMatched && cards[index].isChosen {
            //print("Card not matched, so we're good to go...")
            for var card in cards {
                if card.isChosen {
                    matchingCards.append(card)
                    // see if we have enough cards to match
                    if matchingCards.count > 2 {
                        //TODO: Need to call match logic here and set each matched card to .isMatched = true if matched
                        if card.isMatched {
                          print("Yay, matched!")
                        } else {
                            print("Card is not matched, flipping back over")
                            /*** THIS LINE NOT REFLECTING IN THE UI! ***/
                            card.isChosen = !card.isChosen // flip the unmatched card back over
                        }
                    }
                }
            }
            matchingCards.removeAll() // clear out all the cards from the matching
        } else {
            print("Card is either matched or being deselected...")
        }
    }

你的问题是Card是一个struct,所以这一行:

for var card in cards {

cards 中的每张卡片创建一个副本,因此在该副本上设置任何属性都不会修改 cards 数组中的卡片。

要解决此问题,请遍历数组的 indices 并将卡片引用为 cards[idx]:

struct SetGame {

private(set) var cards = [Card]()
mutating public func chooseCard(at index: Int) {

    //TODO: Assertion here for index being < cards.count
    print("chooseCard(at index: \(index)")
    cards[index].isChosen = !cards[index].isChosen // toggle isChosen when card is selected

    if !cards[index].isMatched && cards[index].isChosen {
        //print("Card not matched, so we're good to go...")
        for idx in cards.indices {
            if cards[idx].isChosen {
                matchingCards.append(cards[idx])
                // see if we have enough cards to match
                if matchingCards.count > 2 {
                    //TODO: Need to call match logic here and set each matched card to .isMatched = true if matched
                    if cards[idx].isMatched {
                      print("Yay, matched!")
                    } else {
                        print("Card is not matched, flipping back over")
                        /*** THIS LINE NOT REFLECTING IN THE UI! ***/
                        cards[idx].isChosen = !cards[idx].isChosen // flip the unmatched card back over
                    }
                }
            }
        }
        matchingCards.removeAll() // clear out all the cards from the matching
    } else {
        print("Card is either matched or being deselected...")
    }
}

或考虑将 Card 设为 class,这样当您引用 Card 时,您就知道您指的是同一个对象。