Проблема с передачей по значению против передачи по ссылке в Swift?

Я новичок в Swift, но не новичок в iOS dev. У меня возникла проблема, которая, по моему мнению, вызвана передачей по стоимости.

Ниже код находится в 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, который на самом деле представляет собой просто колоду карт и отображается обратно на кнопки UIB. При касании карты (UIButton) в VC вызывается метод (выбрать карту) в Struct. Среди прочего, это действие будет переключаться, если карта выбрана путем установки card.isSelected =! Card.isSelected и отображается обратно в пользовательский интерфейс, чтобы указать, выбрана ли карта или нет. Пока все это прекрасно работает.

Когда выбрано 3 карты, это вызывает некоторую логику совпадения, которая в настоящее время просто заглушена. Если совпадений не было, для каждой карты.isSelected устанавливается значение false, поэтому в пользовательском интерфейсе эти карты больше не будут отображаться выбранными. Это то, что не работает, и я не могу понять, почему. Я догадываюсь, что я делаю что-то не так, когда имею дело с передачей по значению, поскольку логический объект является структурой. После того, как выбраны 3 карты, и они не совпадают (они не будут совпадать, так как это только заглушка), для каждого card.isSelected должно быть установлено значение false, но они все еще показывают выбранные в пользовательском интерфейсе. Я установил точку останова в 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...")
        }
    }

1 ответ

Решение

Ваша проблема в том, что 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 Вы знаете, что имеете в виду один и тот же объект.

Другие вопросы по тегам