Как получить доступ к содержимому пользовательской ячейки в Swift с помощью тега кнопки?

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

Мне нужно получить доступ к содержимому выбранной ячейки (с помощью кнопки) и добавить их в массив или словарь. Я новичок в этом, поэтому изо всех сил пытаюсь узнать, как получить доступ к содержимому ячейки. Я пытался использовать didselectrowatindexpath, но я не знаю, как заставить индекс быть индексом тега...

Итак, в основном, если в каждой ячейке есть 3 ячейки с «Собака», «Кошка», «Птица» в качестве cell.repeatLabel.text, и я выбираю кнопки в строках 1 и 3 (индекс 0 и 2), он должен добавьте «Собаку» и «Птицу» в массив/словарь.

    // MARK: - Table View

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return postsCollection.count
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell: CustomCell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! CustomCell

    // Configure the cell...
    var currentRepeat = postsCollection[indexPath.row]
    cell.repeatLabel?.text = currentRepeat.product
    cell.repeatCount?.text = "Repeat: " + String(currentRepeat.currentrepeat) + " of " + String(currentRepeat.totalrepeat)

    cell.accessoryType = UITableViewCellAccessoryType.DetailDisclosureButton

    cell.checkButton.tag = indexPath.row;

    cell.checkButton.addTarget(self, action: Selector("selectItem:"), forControlEvents: UIControlEvents.TouchUpInside)


    return cell

}

func selectItem(sender:UIButton){

    println("Selected item in row \(sender.tag)")

 }

person Steve Rowe    schedule 28.04.2015    source источник


Ответы (6)


ВАРИАНТ 1. Обработка с помощью делегирования

Правильный способ обработки событий, запускаемых из подпредставлений вашей ячейки, — использовать делегирование.

Таким образом, вы можете выполнить следующие шаги:

1. Над определением класса напишите протокол с единственным методом экземпляра внутри пользовательской ячейки:

protocol CustomCellDelegate {
    func cellButtonTapped(cell: CustomCell)
} 

2. Внутри определения вашего класса объявите переменную делегата и вызовите метод протокола для делегата:

var delegate: CustomCellDelegate?

@IBAction func buttonTapped(sender: AnyObject) {
    delegate?.cellButtonTapped(self)
}

3. Соответствуйте CustomCellDelegate в классе, в котором находится ваше табличное представление:

 class ViewController: CustomCellDelegate

4. Установите делегата вашей ячейки

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as CustomCell
    cell.delegate = self

    return cell
}

5. Реализуйте требуемый метод в своем классе контроллера представления.

EDIT: сначала определите пустой массив, а затем измените его следующим образом:

private var selectedItems = [String]()

func cellButtonTapped(cell: CustomCell) {
    let indexPath = self.tableView.indexPathForRowAtPoint(cell.center)!
    let selectedItem = items[indexPath.row]

    if let selectedItemIndex = find(selectedItems, selectedItem) {
        selectedItems.removeAtIndex(selectedItemIndex)
    } else {
        selectedItems.append(selectedItem)
    }
}

где items — это массив, определенный в моем контроллере представления:

private let items = ["Dog", "Cat", "Elephant", "Fox", "Ant", "Dolphin", "Donkey", "Horse", "Frog", "Cow", "Goose", "Turtle", "Sheep"] 

ВАРИАНТ 2. Обработка с помощью замыканий

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

1. Объявите замыкающую переменную внутри класса ячеек:

var tapped: ((CustomCell) -> Void)?

2. Вызвать замыкание внутри обработчика кнопки.

@IBAction func buttonTapped(sender: AnyObject) {
    tapped?(self)
}

3. В tableView(_:cellForRowAtIndexPath:) в содержащем классе контроллера представления:

let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! CustomCell       
cell.tapped = { [unowned self] (selectedCell) -> Void in
    let path = tableView.indexPathForRowAtPoint(selectedCell.center)!
    let selectedItem = self.items[path.row]

    println("the selected item is \(selectedItem)")
}
person Vasil Garov    schedule 28.04.2015
comment
Мне это решение нравится больше, чем то, что выше. Хотя вы забыли упомянуть, что он должен фактически установить делегата. В остальном раствор твердый. - person Andrew Robinson; 28.04.2015
comment
Конечно, я должен был, мой плохой. Будет редактировать его. Спасибо. - person Vasil Garov; 28.04.2015
comment
Большое спасибо, ребята. Это работает как шарм и дало мне небольшое представление о делегате ... все еще очень новичок. - person Steve Rowe; 29.04.2015
comment
Я знаю, что сейчас нажимаю на это, но я хожу по кругу. Мне нужно добавить selectedItem в массив, и я понятия не имею, как это сделать. Я пытался добавить его в фонд cellButtonTapped, но это не сработало. Если я что-то выбираю, он должен добавить это в массив, если я отменяю выбор, он должен удалить это из массива. Идея состоит в том, что как только у меня будет массив, я отправлю результаты выбранных элементов в базу данных mySQL, когда пользователь нажмет кнопку "Отправить"... - person Steve Rowe; 02.05.2015
comment
Что вы пробовали в cellButtonTapped ? И каково именно ожидаемое поведение — нажатие кнопки -> добавить элемент в массив, повторное нажатие -> удалить элемент из массива? - person Vasil Garov; 02.05.2015
comment
Я попробовал что-то вроде var selectedItems : [String] = String, а затем добавил каждый выбор в массив. Это просто добавляет текущий выбранный элемент в массив. То, что вы описали, это именно то, что мне нужно. Чтобы получить исходные данные из базы данных mySQL, у меня есть класс Post (с JSON), который используется для создания массива postCollection. Я полагаю, мне нужно создать обратную сторону этого, чтобы добраться до точки, где я могу отправить то, что было выбрано, обратно в базу данных mySQL. - person Steve Rowe; 02.05.2015
comment
Хорошо, я отредактирую свой ответ. Обратите внимание, что я не на своем Mac и не могу протестировать код. - person Vasil Garov; 02.05.2015
comment
Большое спасибо. Ты звезда. Это сработало отлично. - person Steve Rowe; 02.05.2015
comment
@flashadvanced большое спасибо, все сработало отлично .. но как изменить изображение кнопки, используя вариант 2? - person seggy; 09.12.2016
comment
Я использовал переменную в пользовательском классе ячеек, если я изменяю переменную в действии кнопки, используя метод делегата в другом представлении, чем я могу получить отраженное значение этой переменной в cellforitem. - person Akhilesh Sharma; 10.01.2017

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

let indexPath = NSIndexPath(forRow: tag, inSection: 0)
let cell = tableView.cellForRowAtIndexPath(indexPath) as! CustomCell!

где тег вы получите из тега кнопки.

person Amit89    schedule 28.04.2015
comment
он не будет работать каждый раз, даже если это один раздел. Предположим, вы удалили одну ячейку из таблицы, и если вы получите доступ к тегу как indexPath, он даст вам неправильный индекс. так что будьте осторожны с этим... - person Jay Patel; 12.07.2017

Swift 3 Я просто получаю решение для ячейки доступа в функции @IBAction, используя суперпросмотр тега кнопки.

let cell = sender.superview?.superview as! ProductCell
var intQty = Int(cell.txtQty.text!);
intQty = intQty! + 1
let  strQty = String(describing: intQty!);
cell.txtQty.text = strQty
person Shailesh Talaviya Php Freelanc    schedule 03.01.2017

Я обновил вариант 1 ответа Василя Гарова для Swift 3.

1. Создайте протокол для своего CustomCell:

protocol CustomCellDelegate {
    func cellButtonTapped(cell: CustomCell)
} 

2. Для вашего TableViewCell объявите переменную delegate и вызовите для нее метод протокола:

var delegate: CustomCellDelegate?

@IBAction func buttonTapped(sender: AnyObject) {
    delegate?.cellButtonTapped(self)
}

3. Соблюдайте CustomCellDelegate в классе, где находится ваш tableView:

 class ViewController: CustomCellDelegate

4. Установите delegate своей ячейки

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)  as CustomCell
    cell.delegate = self

    return cell
}

5. Реализуйте требуемый метод в файле ViewController.

person Herr der Töne    schedule 07.03.2017

Основываясь на ответе Цао, вот решение для обработки кнопок в ячейке представления коллекции.

    @IBAction func actionButton(sender: UIButton) {
        let point = collectionView.convertPoint(sender.center, fromView: sender.superview)
        let indexPath = collectionView.indexPathForItemAtPoint(point)
}

Имейте в виду, что вызов функции convertPoint() преобразует координаты точки кнопки в пространство просмотра коллекции. Без indexPath всегда будет ссылаться на один и тот же номер ячейки 0

person CyrIng    schedule 03.04.2016

XCODE 8: важное примечание

Не забудьте установить для тегов значение, отличное от 0.

Если вы попытаетесь создать объект с тегом = 0, это может сработать, но в некоторых странных случаях это не сработает.

Исправление состоит в том, чтобы установить теги на разные значения. Надеюсь, это поможет кому-то.

person MLBDG    schedule 14.04.2017