我在TableViewCell中有一个UIView,当用户点击这个UIView时,它会转到另一个视图控制器并传递数据。
所以在TableViewCellClass里面我做了以下几点:
当用户列出UIView时,我设置了一个协议并检测到“Tap”手势。这部分工作正常:
protocol MyDelegate : class {
func runThisFunction(myString : String)
}
class MyTableViewCell: UITableViewCell {
weak var delegate : MyDelegate?
...other code here
//here detect the tap
let tap = UITapGestureRecognizer(target: self, action: #selector(hereTapped))
self.myUIElementInThisCell.addGestureRecognizer(tap)
}
@objc func hereTapped(sender: UITapGestureRecognizer? = nil){
self.delegate?.runThisFunction(myString: "I am a man")
}
所以在包含这个TableView的视图控制器中,我完成了以下操作:
我将MyDelegate
扩展为子类,然后在其中附加协议函数,如下所示
class MyViewController: UIViewController,MyDelagate{
func runThisFunction(myString : String) {
print("Tapped in view controller")
self.performSegue(withIdentifier: "MySegue",sender : self)
}
override func viewDidLoad() {
super.viewDidLoad()
let tableViewCell = MyTableViewCell()
tableViewCell.delegate = self
}
}
结果:
在完成上述所有内容之后,当我点击qazxsw poi时,它没有执行qazxsw poi中所述的segue,即使UIView
命令也没有执行。
那么我错过了什么?请给我一个解决方案。谢谢
问题在你的MyViewControllerClass
:
print()
基本上,您不是为正在呈现的单元格设置委托,而是为您在viewDidLoad
中创建的另一个实例设置委托。
你必须在// you create a new cell
let tableViewCell = MyTableViewCell()
// set its delegate
tableViewCell.delegate = self
// and then the cell is not used for anything else
中设置一个委托,以确保正确的单元格得到viewDidLoad
集:
cellForRowAt
这将为那些呈现的细胞设置delegate
。
或者,我建议使用来自override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "yourIdentifier", for: indexPath) as! MyTableViewCell
cell.delegate = self
return cell
}
的delegate
(如果你的didSelectRowAt
实现它):
UITableViewDelegate
问题是没有定义MyViewController
实例的委托。
当你这样做时:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.row == 0 { // only if it is the first cell (I assume that MyTableViewCell is first)
runThisFunction(myString: "I am a man")
}
}
您正在设置一个对象的委托,该对象将在方法MyTableViewCell
完成时被销毁。
解决方案1
为了避免这种情况,您必须在override func viewDidLoad() {
super.viewDidLoad()
let tableViewCell = MyTableViewCell()
tableViewCell.delegate = self
}
方法中设置委托。
viewDidLoad()
解决方案2
您还可以使用cellForRow
方法捕获用户与单元格的交互。
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "identifier", for: indexPath) as! MyTableViewCell
cell.delegate = self
// Other configurations
return cell
}
这样你就避免了所有的UITableViewDelegate
事情。这将是我的首选。
问题是这两行:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)
self.performSegue(withIdentifier: "MySegue",sender : self)
}
与表中显示的单元格无关,它是一个动态创建的单元格
在MyDelegate protocol
中为您将实际等待委托触发器的单元格设置委托
let tableViewCell = MyTableViewCell()
tableViewCell.delegate = self
像这样
cellForRow
这里的委托不是很好,确实如果你想要更改未明确传递给单元格的对象。
我的建议是使用闭包:
cell.delegate = self
并从视图控制器设置它
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = areaSettTable.dequeueReusableCell(withIdentifier:cellID) as! MyTableViewCell
cell.delegate = self
}
PS:正如我所说,通常你想进一步传递与细胞相关的对象。使用委托很困难,因为你不得不传递一些额外的标记,通过单元确定对象,o传递对象本身打破模型 - 视图分离范例。但是它可以通过闭包轻松完成:
typealias CellTapHandler = (String)->()
class CustomCell: UITableViewCell {
var handler: CellTapHandler?
@objc func hereTapped(sender: UITapGestureRecognizer? = nil) {
handler?("String or whatever you want to get back from cell.")
}
//...
}