当点击表格视图中的元素时,如何转到另一个视图控制器?

问题描述 投票:0回答:4

我在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命令也没有执行。

那么我错过了什么?请给我一个解决方案。谢谢

ios swift swift4
4个回答
0
投票

问题在你的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

1
投票

问题是没有定义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事情。这将是我的首选。


1
投票

问题是这两行:

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

0
投票

这里的委托不是很好,确实如果你想要更改未明确传递给单元格的对象。

我的建议是使用闭包:

 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.")
    }
    //...
}
© www.soinside.com 2019 - 2024. All rights reserved.