Swift: изменение массива UIB-кнопок путем передачи по ссылке - PullRequest
0 голосов
/ 22 января 2019

Проблема: Невозможно передать неизменяемое значение в качестве аргумента inout: 'cardView' - это константа 'let'

Решение 1, которое я нашел (но с нежелательным поведением): Код работает нормально, когда я просто пропускаю входные объявления и "&". Но представление не обновляется сразу.

// Line 3: updateCardView(...) is producing the error   
private func updateViewFromModel() {
        ...
        for (index, cardView) in cardsContainerView.cardViews.enumerated() {
            updateCardView(game.handedOutCards[index], &cardView)       
        }
  }

   private func updateCardView (_ card: Card, _ cardView: inout CardView)  {
       cardView.layerState(cardView: &cardView)
       cardView.layer.borderColor = #colorLiteral(red: 0.2196078449, green: 0.007843137719, blue: 0.8549019694, alpha: 1).cgColor
  }


class CardsContainerView: UIView {
    var cardViews = [CardView](){
    didSet {
        setNeedsLayout()
    }
}

class CardView: UIButton {
     func layerState(cardView: inout CardView) {
         cardView.layer.cornerRadius = 3
         cardView.layer.borderWidth = 2 
     }
 }

Решение 2 работает, но только когда layerState () пусто:

private func updateViewFromModel() {
     ...
     for index in cardsContainerView.cardViews.indices {
         updateCardView(game.handedOutCards[index], cardsContainerView.cardViews[index])       
     }
}

private func updateCardView (_ card: Card, _ cardView: CardView)  {
    cardView.layer.borderWidth = 2
    cardView.layerState()
    cardView.layer.borderColor = #colorLiteral(red: 0.2196078449, green: 0.007843137719, blue: 0.8549019694, alpha: 1).cgColor
}


class CardsContainerView: UIView {
    var cardViews = [CardView](){
    didSet {
        setNeedsLayout()
    }
}

class CardView: UIButton {
     func layerState() {
         // Setting a border within this function is not working as expected
         // The borders of the cards are only shown after another touch event and only for old objects of cardViews
         //self.layer.borderWidth = 2
     }
 }

Ожидаемый результат : Каждая новая кнопка должна иметь рамку, отображаемую сразу после ее создания и обновления представления. Параметры границы должны быть установлены в пределах layerState().

Фактический результат: При установке значения borderWidth в пределах layerState() граница не отображается сразу. Однако после другого события касания уже существующие экземпляры cardView имеют ожидаемую границу.

1 Ответ

0 голосов
/ 22 января 2019

cardView - это константа let, поскольку она создается циклом for. Вы можете сделать его var, добавив ключевое слово var:

for (index, var cardView) in cardsContainerView.cardViews.enumerated() {
    updateCardView(game.handedOutCards[index], &cardView)       
}

Но это своего рода беспорядок, потому что вы все еще создаете новую переменную, которая является ссылкой на переменную в массиве, и затем передаете эту переменную. Это работает, потому что и переменная в массиве, и новая переменная являются ссылками на объект вашей карты, но вся вещь inout является пустой тратой, потому что вы просто отбрасываете копию cardView в следующей итерации цикла.

Вы можете изменить свой цикл на:

for index in cardsContainerView.cardViews.indices {
    updateCardView(game.handedOutCards[index], &cardsContainerView.cardViews[index])       
}

Здесь вы используете index, чтобы найти и передать значение непосредственно из массива, поэтому элемент массива будет обновлен. Это даже сработало бы, если бы cardView было struct вместо class.

Поскольку вы работаете с class, вы можете обновлять объекты, не используя inout.


Вы должны использовать self для обновления объекта вместо inout для передачи ссылки:

class CardView: UIButton {
     func layerState() {
         self.layer.cornerRadius = 3
         self.layer.borderWidth = 2 
     }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...