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