簡體   English   中英

當點擊表視圖內的元素時,如何轉到另一個視圖控制器?

[英]How to go to another View Controller when an element inside table view is being tapped?

我在TableViewCell中有一個UIView,當用戶在此UIView中點擊時,它會轉到另一個視圖控制器並傳遞數據。

因此,在TableViewCellClass內部,我執行了以下操作:

我在用戶表UIView時設置了協議並檢測到“輕按”手勢。這部分工作正常:

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
 }
}

結果:

完成上述所有操作后,當我點擊UIView ,它沒有執行MyViewControllerClass所述的MyViewControllerClass ,甚至print()命令也沒有執行。

那我錯過了什么呢? 請給我一個解決方案。謝謝

問題是這兩行:

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
   }

問題是MyTableViewCell實例的委托未定義。

當您這樣做時:

override func viewDidLoad() {
    super.viewDidLoad()

    let tableViewCell = MyTableViewCell()
    tableViewCell.delegate = self
}

您正在為一個對象設置委托,該委托將在方法viewDidLoad()完成時銷毀。

解決方案1

為了避免這種情況,您必須在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
}

解決方案2

您還可以使用UITableViewDelegate方法來捕獲與單元格的用戶交互。

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let cell = tableView.cellForRow(at: indexPath)

    self.performSegue(withIdentifier: "MySegue",sender : self)
}

這樣,您可以避免所有MyDelegate protocol 這將是我的首選。

問題出在您的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


另外,我建議使用UITableViewDelegate didSelectRowAt (如果您的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")
    }
}

這里的委托不是很好,的確,如果您要更改未明確傳遞給單元的對象,則確實如此。

我的建議是使用閉包:

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.")
    }
    //...
}

並從視圖控制器進行設置

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "yourIdentifier", for: indexPath) 
    (cell as? MyTableViewCell).handler = { [weak self] string in  } 
    return cell
}

PS:正如我所說,通常您想進一步傳遞與單元格相關的對象。 委派是很難做到的,因為您必須傳遞一些額外的令牌給單元格,以便由單元格確定對象,否則傳遞對象本身會破壞Model-View分離范式。 但這可以通過閉包輕松完成:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let object = self.myData[indexPath.row]
    let cell = tableView.dequeueReusableCell(withIdentifier: "yourIdentifier", for: indexPath) 
    (cell as? MyTableViewCell).handler = { [weak self] string in  
          self.performSegue(withIdentifier: "MySegue",sender : object)
    } 
    return cell
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
     if (let myObj = sender as? MyObjType, let subsequentVC = segue.destination as? NextViewController) {
           subsequentVC.selectedMyObject = myObj
     }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM