Доступ ко всем ячейкам при нажатии кнопки в ячейке - PullRequest
1 голос
/ 24 октября 2019

У меня есть UITableView с пользовательским UITableViewCell. В каждой ячейке есть кнопка, и я бы хотел, чтобы при нажатии одной кнопки все кнопки были не щелкаемыми. Легко получить доступ к ячейке, в которой находится нажатая кнопка, но мне также нужно получить доступ ко всем остальным ячейкам, чтобы сделать их кнопку не щелкающей.

Поэтому, когда кнопка нажимается внутри ячейки, мне нужно просмотреть вседругие ячейки ... Я нашел способ пройти вверх по иерархии, чтобы в методе действия кнопки я поднялся на один уровень выше, чтобы получить доступ к UITableView, и оттуда я могу получить доступ к каждой ячейке, и из каждой ячейки я могу получить доступ к их кнопкеи отредактируйте свойство isUserInteractionEnabled. Однако это не очень хорошая практика, чтобы сделать ячейку доступной к TableView, а затем ко всем другим ячейкам.

class AnswerCell2: UITableViewCell {

let answerTextButton: UIButton = {
        let answerButton = UIButton()
        answerButton.setTitle("initial text", for: .normal)
        return answerButton
    }()


override init(style: UITableViewCell.CellStyle, reuseIdentifier: String!) {

       answerTextButton.addTarget(self, action: #selector(answerClicked), for: .touchUpInside)

}

@objc func answerClicked(sender: UIButton) {
// HERE I CAN ACCESS EASILY THE CELL WHERE THE BUTTON WAS CLICKED 
// AND THEN USE THE TABLEVIEW TO ACCESS OTHER CELLS AND THEIR BUTTONS 
// BUT THIS IS NOT A NICE WAY
    }

Итак, у меня есть решение, как я уже сказал, но я бы хотел больше приятногоспособ сделать это. Все решения, которые я нахожу в Интернете, связаны с тем, как получить доступ к ячейке, в которой была нажата кнопка, но это просто, мне нужно получить доступ к другим ячейкам, и я бы хотел, по возможности, избегать этого в методе действия answerClicked (). так что код остается чистым.

Спасибо.

Ответы [ 3 ]

0 голосов
/ 24 октября 2019

Вы можете создать closure в пользовательском UITableViewCell и вызывать его при каждом нажатии button в cell, т.е.

class TableViewCell: UITableViewCell {
    @IBOutlet weak var button: UIButton!
    var handler: (()->())?

    @IBAction func buttonClicked(_ sender: UIButton) {
        handler?()
    }
}

Теперь установите closure в tableView(_:cellForRowAt:) метод и использование свойства visibleCells для включения / выключения buttons в других cells, т.е.

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell
    cell.textLabel?.text = arr[indexPath.row]
    cell.handler = {
        if let visibleCells = tableView.visibleCells as? [TableViewCell] {
            visibleCells.forEach({
                $0.button.isEnabled = ($0 === cell)
            })
        }

    }
    return cell
}

В случае, если вы хотите сохранить разрешение / отключить button состояний при перезагрузке, вам нужно сохранить в вашем model.

0 голосов
/ 24 октября 2019

Это может быть достигнуто при относительно легком подходе с помощью функций замыкания или делегирования. Учитывая, что tableView уже перегружен делегатами, я бы немного предпочел такой подход.

создайте простой протокол, чтобы позволить ячейке информировать viewController

protocol CellStateRespondable {  //I'm sure there are better protocol names than this!
  var buttonsAreEnabled: Bool
  func cellButtonChangedSate(enabled: Bool)
}

Добавить переменную делегата в ваш класс AnswerCell2

weak var delegate: CellStateRespondable?

и адаптируйте answerClicked(sender: UIButton) для вызова метода делегата

delegate?.cellButtonChangedState(enabled: sender.isEnabled)

, чтобы ViewController (или другой контроллер, если вы разделили функции делегата tableView) соответствовали протоколу путем добавленияпеременную и функцию, и добавьте реализацию функции

var buttonsAreEnabled = true

func cellButtonChangedSate(enabled: Bool) {
  buttonsAreEnabled = enabled
  if let visibleCells = tableView.visibleCells as? [AnswerCell2] {
    visibleCells.forEach {
      $0.button.isEnabled = enabled
    }
  }
}

, а затем адаптируйте свой cellForRowAt для установки делегата и состояния кнопки при создании ячейки

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  let cell = //dequeue cell and configure as normal
  cell.delegate. = self
  cell.button.isEnabled = buttonsAreEnabled
  return cell
}
0 голосов
/ 24 октября 2019

Я не уверен, зачем вам нужно идти по иерархии и конкретно изменять характеристики существующих ячеек на экране.

Просто сохраните значение, которое представляет индекс выбранной кнопки.

var indexPathForSelectedButton: IndexPath?

Каждый раз, когда это изменяется, обновите индекс в func answerClicked(sender: UIButton) и перезагрузите представление таблицы.

в ячейке для метода at, проверьте, совпадает ли текущий indexPath с сохраненным, и, если это так, активируйте кнопку, отключите, если нет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...