【问题标题】:Issue with pass by value vs pass by reference in Swift?Swift 中按值传递与按引用传递的问题?
【发布时间】:2019-01-20 14:46:32
【问题描述】:

我是 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...")
        }
    }

【问题讨论】:

  • Cardstruct 还是 class
  • 结构。抱歉,忘记提了。

标签: ios swift pass-by-reference pass-by-value


【解决方案1】:

您的问题是Cardstruct,所以这一行:

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 时,您就知道您指的是同一个对象。

【讨论】:

  • 啊!非常感谢!我认为这是我沿着这条路线做的事情导致了这个问题。我想把它变成一个类,但是从我正在学习的 Swift 课程中,他们说最好的做法是使用结构,除非你真的需要一个类,比如继承等。我更喜欢引用类型而不是值出于这样的原因类型,但尝试学习 Swift 方式。感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 2016-10-22
  • 2023-03-02
  • 2012-07-03
  • 1970-01-01
  • 2013-04-12
  • 2020-05-18
相关资源
最近更新 更多