Как запретить зеркальному отображению нажатие кнопки в другой ячейке? - PullRequest
0 голосов
/ 29 октября 2019

У меня есть 3 кнопки в ячейках моего табличного представления, они находятся в коллекции кнопок @IBAction, поэтому при выборе одной из них цвет кнопки меняется с синего на красный и отменяется выбор ранее нажатой кнопки, чтобы вернуться к синему. код прекрасно работает при выполнении этих действий

проблема, с которой я сталкиваюсь, заключается в том, что когда кнопка выбрана в одной ячейке, точно такая же кнопка будет выбрана в другой ячейке, как показано ниже ▼

пока что то, что я пробовал, не работает, и я думаю, что может сработать то, что я создаю «@objc func» в контроллере представления, но я не знаю, куда идти от того, что я создал, чтобы предотвратить «зеркальное отображение» в ячейках

Я знаю, что я близок к решению, заранее благодарю за любую помощь, которую вы оказываете

Как обновить UILabel по нажатию кнопки в UITableViewCell в swift 4 и xcode 9?

cell image

import UIKit

class Cell: UITableViewCell {

    @IBOutlet weak var lbl1: UILabel!
    @IBOutlet weak var lbl2: UILabel!
    @IBOutlet weak var lbl3: UILabel!

    @IBOutlet weak var btn1: RoundButton!
    @IBOutlet weak var btn2: RoundButton!
    @IBOutlet weak var btn3: RoundButton!

    var lastSelectedButton = UIButton()
    @IBAction func cartTypeSelected(_ sender: RoundButton) {
        lastSelectedButton.isSelected = false; do {
            self.lastSelectedButton.backgroundColor = UIcolor.blue
        } //Plus any deselect logic for this button
        lastSelectedButton = sender //If any buttons are not affect by this selection logic exclude them here
        sender.isSelected = true; do {
            self.lastSelectedButton.backgroundColor = UIColor.red
        }
    }
}

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!

    override func viewDidLoad() {
         super.viewDidLoad()

         tableView.dataSource = self
         tableView.delegate = self

    }
    var lastSelectedButton = UIButton()
    @objc func selectedButton(_ sender: RoundButton) {
        lastSelectedButton.isSelected = false; do {
            self.lastSelectedButton.backgroundColor = UIcolor.blue
        } //Plus any deselect logic for this button
        lastSelectedButton = sender 
        sender.isSelected = true; do {
            self.lastSelectedButton.backgroundColor = UIColor.red
        }
    }
}

extension View[![enter image description here][1]][1]Controller: UITableViewDelegate, UITableViewDataSource {
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 100
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as? Cell else { return UITableViewCell() }

        return cell
    }
}

Ответы [ 2 ]

1 голос
/ 29 октября 2019

Привет, Эвелин! Используйте шаблон делегирования! :)

Вот несколько пояснений, которые помогут вам продолжать:

  1. создать модель для представления содержимого вашего табличного представления

Какого родамодели мы могли бы использовать, чтобы представить состояние, когда выбрана только одна кнопка? Перечисление может представлять это (добавить его в отдельный файл или в ваш контроллер):

enum ButtonSelectionIdentity {
    case first
    case second
    case third
}

В нашем табличном представлении будет представлен массив этих перечислений, в контроллере, давайте добавим переменную экземпляра вудерживайте данные и инициализируйте их пустым массивом:

private var elements: [ButtonSelectionIdentity] = []

Давайте заполним этот массив 100 элементами, по умолчанию выбирая первую кнопку в функции контроллера viewDidLoad, добавив:

    for i in 0..<100 {
        elements.append(ButtonSelectionIdentity.first)
    }
убедитесь, что ячейки обновлены из модели

Итак, теперь у нас есть модель (массив ButtonSelectionIdentity), и мы хотим, чтобы контроллер табличного представления отражал эту модель. Для этого мы изменим первоначальный способ соответствия контроллера UITableViewDataSource. Нам нужна новая реализация для получения данных из массива:

extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return elements.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as? Cell else { 
            return UITableViewCell() 
        }

        let model = elements[indexPath.row]
        cell.update(with: model)

        return cell
    }
}

Да, после изменения, указанного выше, оно не скомпилируется, пока мы не добавим метод обновления в класс ячейки:

func update(with model: ButtonSelectionIdentity) {
    btn1.backgroundColor = .blue
    btn2.backgroundColor = .blue
    btn3.backgroundColor = .blue

    switch model {
    case .first:
        btn1.backgroundColor = .red
    case .second:
        btn2.backgroundColor = .red
    case .third:
        btn3.backgroundColor = .red
    }
}

Скомпилируйте и запустите, вы должны увидеть 100 клеток с первым квадратом красного цвета.

Позволяет связать действия ячеек с контроллером

Удалите метод buttonSelected из вашего класса контроллера и удалите метод btnTypeSelected из вашего класса Cell, чтобы мы могли начать все сначала. .

На этом этапе у нас есть массив элементов, представленных в табличном представлении внутри контроллера. Контроллер владеет им, потому что он его создал. Ячейки предназначены только для представления состояния, которое имеет контроллер. Итак, чтобы заставить нашу ячейку обновляться, мы должны сообщить контроллеру, что мы обновляем. Для этого мы можем использовать шаблон делегирования. Давайте создадим протокол делегата ячейки для его описания.

В вашем файле класса Cell перед class Cell ... добавьте:

protocol CellDelegate: class {
    func onCellModelChange(cell: Cell, model: ButtonSelectionIdentity)
}

Так что это тот делегат, который мы будем использовать длясообщите контролеру об изменении состояния в ячейке. Добавим слабую ссылку на ячейку для делегата. В вашем Cell добавьте:

weak var delegate: CellDelegate?

Теперь, настройте ваш контроллер на CellDelegate протокол. В вашем классе контроллера добавьте:

extension ViewController: CellDelegate {
    func onCellModelChange(cell: Cell, model: ButtonSelectionIdentity) {
    }
}

, а пока мы оставим его пустым и завершим его позже.

Теперь контроллер может быть делегатом ячейки. Давайте сделаем это, чтобы быть одним! Обновите метод cellForRowAt вашего контроллера следующим образом:

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as? Cell else { 
            return UITableViewCell() 
        }

        let model = elements[indexPath.row]
        cell.update(with: model)
        cell.delegate = self

        return cell
    }

Готово, мы настроили наш контроллер как делегат ячейки! Давайте использовать это как-то!

Создание модели обновления контроллера, когда ячейка сообщает об изменении ее состояния

В вашей ячейке подключите IBActions для каждой кнопки отдельно:

@IBAction func onFirstButtonTapped(_ sender: RoundButton) {
}

@IBAction func onSecondButtonTapped(_ sender: RoundButton) {
}

@IBAction func onThirdButtonTapped(_ sender: RoundButton) {
}

Всякий раз, когданажата кнопка, мы хотим, чтобы наша ячейка сообщала контролеру об изменении состояния, например:

@IBAction func onFirstButtonTapped(_ sender: RoundButton) {
    delegate?.onCellModelChange(cell: self, model: .first)
}

Реализуйте два других метода соответствующим образом.

В вашем контроллере давайте вернемся к onCellModelChange метод. Теперь, когда произошло действие с ячейкой, нам нужно найти элемент в массиве elements, соответствующий этой ячейке. Чтобы сделать это, мы можем использовать метод tableView -s -indexPath(for:):

extension ViewController: CellDelegate {
    func onCellModelChange(cell: Cell, model: ButtonSelectionIdentity) {
        guard let indexPath = tableView.indexPath(for: cell) else {
            return
        }
        print(indexPath)
    }
}

Если вы запустите приложение, на этом этапе вы должны увидеть журналы указателей, соответствующие ячейкам, которые вы нажимаетекнопки включены. Не совсем то, что нам нужно.

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

extension ViewController: CellDelegate {
    func onCellModelChange(cell: Cell, model: ButtonSelectionIdentity) {
        guard let indexPath = tableView.indexPath(for: cell) else {
            return
        }
        let index = indexPath.row
        elemets[index] = model
    }
}

Теперь, если вы запустите это, вы должны обновить модель, но состояние ячейки не будет обновляться сразу. Вы по-прежнему можете видеть, как оно работает, если прокрутить ячейку за пределами экрана и снова прокрутить назад.

Последний бит обновляет ячейку сразу. Как мы можем сделать это? Давайте просто поместим обновленную модель обратно в ячейку:

extension ViewController: CellDelegate {
    func onCellModelChange(cell: Cell, model: ButtonSelectionIdentity) {
        guard let indexPath = tableView.indexPath(for: cell) else {
            return
        }
        let index = indexPath.row
        elemets[index] = model
        cell.update(with: model)
    }
}

И это должно быть! Я не проверял и не компилировал :) Так что, если вы найдете какие-либо опечатки, дайте мне знать :) Cheers

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

Вы используете dequeuereusablecell в своем табличном представлении. Эти ячейки можно использовать повторно, как следует из названия. Это означает, что когда вы прокручиваете свое табличное представление, некоторые аспекты пользовательского интерфейса ячеек могут вести себя одинаково.

Чтобы предотвратить это, вам всегда нужен оператор «else».

sender.isSelected = true; do {
    self.lastSelectedButton.backgroundColor = UIColor.red
}

Если вы не предоставите оператор else, очень вероятно, что вы увидите еще один красный цвет в других ваших ячейках.

...