#ios #delegates #protocols #swift3
#iOS #делегаты #протоколы #swift3
Вопрос:
У меня есть ранее работавший делегат и протокол, который с момента преобразования в Swift 3 больше не вызывается.
protocol TaskCellDelegate {
func doneHit(_ cell : TaskCell)
}
class TaskCell : UITableViewCell {
var delegate : TaskCellDelegate?
@IBOutlet weak var label: UILabel!
@IBOutlet weak var detailLabel: UILabel!
@IBOutlet weak var _checkBox: M13Checkbox!
override func awakeFromNib() {
super.awakeFromNib()
let tap = UITapGestureRecognizer(target: self, action: #selector(TaskCell.buttonClicked(_:)))
tap.numberOfTapsRequired = 1
_checkBox.addGestureRecognizer(tap)
_checkBox.isUserInteractionEnabled = true
_checkBox.markType = .checkmark
_checkBox.boxType = .circle
_checkBox.stateChangeAnimation = .expand(.fill)
}
func buttonClicked(_ sender:UITapGestureRecognizer) {
delegate?.doneHit(self)
}
}
Как вы можете видеть, когда нажата _checkBox, она должна вызывать функцию doneHit в моем классе (не добавлена, потому что это не кажется необходимым, но я могу), но я установил точку останова, и она никогда не вызывается. Я установил свой делегат и соответствовал протоколу в своем классе, но ничего не происходит. Функция doneHit должна обновлять мой серверный сервер, но она не вызывается. Если вам нужна дополнительная информация, я могу предоставить.
Редактировать 1:
class TasksTVC: UITableViewController, TaskCellDelegate {
func doneHit(_ cell:TaskCell) {
if let indexPath = self.tableView.indexPath(for: cell) {
task = tasksInSectionArray[indexPath.section][indexPath.row]
if task.done == false {
cell._checkBox.setCheckState(.checked, animated: true)
task.done = true
task.completedBy = user
cell.detailLabel.text = "Completed By: (task.completedBy)"
cell.label.textColor = UIColor.gray
print("cell checked")
}
else {
cell._checkBox.setCheckState(.unchecked, animated: true)
task.done = false
task.completedBy = ""
cell.detailLabel.text = ""
cell.label.textColor = UIColor.black
print("cell unchecked")
}
fb.updateTaskDoneBool(ref, taskID: task.id, taskDone: task.done)
fb.updateTaskCompletedBy(ref, taskID: task.id, taskCompletedBy: task.completedBy)
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TaskCell", for: indexPath) as! TaskCell
cell.selectionStyle = .none
task = tasksInSectionArray[indexPath.section][indexPath.row]
cell.label.text = task.title
if task.done == true {
cell._checkBox.setCheckState(.checked, animated: true)
cell.detailLabel.text = "Completed By: (task.completedBy)"
cell.label.textColor = UIColor.gray
}
else {
cell._checkBox.setCheckState(.unchecked, animated: true)
cell.detailLabel.text = ""
cell.label.textColor = UIColor.black
}
doneHit(cell)
cell.delegate = self
return cell
}}
Комментарии:
1.
buttonClicked
вызывается? Покажите свойcellForRowAtindexPath
метод.
Ответ №1:
Похоже, вы неправильно установили delegate
свойство в своем TaskCell
экземпляре, я приведу очень простой пример, надеюсь, это поможет вам уловить проблему:
Результат (отредактирован)
Код
TableViewController
import UIKit
protocol TaskCellDelegate {
func doneHit(_ cell: TaskCell)
}
class TableViewController: UITableViewController, TaskCellDelegate {
func doneHit(_ cell: TaskCell) {
let alert = UIAlertController(
title: "Info",
message: "button touched in cell",
preferredStyle: .alert
)
present(alert, animated: true, completion: nil)
}
}
extension TableViewController {
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TaskCell
cell.delegate = self // probably you forgot to set this part?
return cell
}
}
Ячейка задачи (отредактирована)
Вместо создания нового UITapGestureRecognizer
для прикрепления к флажку вы можете использовать addTarget
метод для прикрепления обработчика событий к UIControlEvents.valueChanged
значению.
import UIKit
import M13Checkbox
class TaskCell: UITableViewCell {
var delegate: TaskCellDelegate?
@IBOutlet weak var checkbox: M13Checkbox!
override func awakeFromNib() {
super.awakeFromNib()
checkbox.addTarget(self, action: #selector(buttonClicked), for: .valueChanged)
}
func buttonClicked() {
delegate?.doneHit(self)
}
}
Комментарии:
1. Это не учитывает, что я вызвал buttonClicked как действие в моем распознавателе жестов касания. Это означает, что у меня есть кнопка, созданная в IB, и я использую ее для запуска функции.
Ответ №2:
Существуют следующие случаи, если делегат не вызывается:
- Действие:
buttonClicked
не вызывается. -
Контроллер представления не соответствует протоколу.
class ViewController: UIViewController, TaskCellDelegate {
-
Метод протокола не реализован внутри контроллера представления.
func doneHit(_ cell : TaskCell) { print("delegate implementation called") }
-
Делегат не назначен в
cellForRowAtIndexPathMethod:
cell.delegate = self
Комментарии:
1. Пожалуйста, ознакомьтесь с изменениями. Я сделал все эти вещи. Вся эта ситуация работала просто отлично, прежде чем я выполнил переход на swift 3.