【问题标题】:Accessing a UITableViewController delegate from a TableView header从 TableView 标头访问 UITableViewController 委托
【发布时间】:2021-08-23 15:57:39
【问题描述】:

我在从与以编程方式创建的 TableView 关联的 TableView 标头中调用 segue 时遇到问题。作为权宜之计,我使用 Singleton 保存了对主 UITableViewController 的对象引用,但这不是理想的解决方案。

我的 TableViewController 有多个部分,每个部分中有 1 行或 2 行,具体取决于是否选择了顶级部分行。第二行有效地用于扩展所选行上显示的内容。

第二行包含一个自定义单元格,其中包含一个滑块菜单,并且根据所选的菜单项,容器视图中显示 5 个子视图中的 1 个。

其中一个子视图包含一个以编程方式生成的 TableView,它具有自己的自定义标题和自定义单元格。此单元格包含一个标题和一个嵌入式按钮。当在标题中按下按钮时,我想切换到另一个导航控制器,但是,我的问题是我无法正确初始化委托以访问主 TableViewController。

它变得有点复杂,因为自定义单元格创建了自己的 TableView 并处理自己的函数,这些函数通常在主控制器上使用覆盖来执行,例如didSelectRowAt、numberOfRowsInSelection、headerForRowAt 等

class pendingNotificationCustomCell: UITableViewCell, UITableViewDataSource, UITableViewDelegate {
    
    var dataSample:[String] = ["Row 1,"Row 2", "Row 3"]
    var PendingTableView: UITableView?
   
    required init(coder aDecoder: NSCoder) {
        
        fatalError("init(coder:) has not been implemented")
    }

    override func awakeFromNib() {

        print("##### awakeFromNib")
        super.awakeFromNib()
        // Initialization code
        setUpTable()
    }
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        
        super.init(style: style , reuseIdentifier: reuseIdentifier)
        setUpTable()
    }

    func setUpTable() {
        
        PendingTableView = UITableView(frame: CGRect.init(), style:UITableView.Style.plain)
        
        PendingTableView?.delegate = self
        PendingTableView?.dataSource = self
        
        PendingTableView?.register(MyCell.self, forCellReuseIdentifier: "pendingnotificationsCellID")
        
        PendingTableView?.register(PendingNotificationsHeader.self, forHeaderFooterViewReuseIdentifier: "pendingHeaderID")
        
        PendingTableView?.sectionHeaderHeight = 40
        
        PendingTableView?.allowsSelection = true
        
        PendingTableView?.allowsMultipleSelection = false
        
        self.addSubview(PendingTableView!)
    }

我可以轻松设置协议和关联的委托,以访问管理主 TableView 自定义单元格的控制器上的功能。但是,由于有问题的自定义单元不继承与执行 segues 相关的函数,我需要访问主控制器上的函数。

我已经对此进行了相当多的试验,但除了 Singleton hack 之外,还没有提出可行的解决方案。

    let pendingCell = pendingNotificationCustomCell()
    
    pendingCell.delegate4 = mStats.mainController

当我尝试为 delegate4 分配一个引用主 TableViewController 的初始化出口时,它到达那里时总是有一个值“nil”。即使我在类中为它分配单例值,也会生成第二个 表视图。注释掉的行失败,而使用 mStats Singleton 调用该方法工作正常。

        //delegate4.callSegueFromCell2(myData: myData) 
        mStats.mainController?.callSegueFromCell2(myData: myData)

上面被注释掉的delegate4在cell header classes中设置如下:

    protocol MyCustomCellDelegator3 {
    func callSegueFromCell2(myData dataobject: AnyObject)
}
class PendingNotificationsHeader: UITableViewHeaderFooterView {
    
    var delegate4:MyCustomCellDelegator3!
    
    var MainTableViewController: MainTableViewController?
    
    override init(reuseIdentifier: String?) {
        
        super.init(reuseIdentifier: reuseIdentifier)
        setupViews()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    let nameLabel: UILabel = {
        let label = UILabel()
        label.text = "Pending"
        label.font = UIFont.systemFont(ofSize: 17)
        label.textColor = .white
        return label
    }()
    
    let priceAlertButton: UIButton = {
        let button = UIButton(type: .system)
        button.setTitle("Add new", for: .normal)
        button.titleLabel?.font = UIFont (name: "Helvetica", size: 15)
        button.setTitleColor(.white, for: .normal)
        button.addTarget(self,action: #selector(createNewPriceAlertButtonPressed), for: .touchUpInside)
        return button
    }()
    
    @IBAction func createNewPriceAlertButtonPressed(_ sender: Any) {
        print ("##### New Price Alert Label Pressed")
        // Get the view
        
        var mydata = self

        //delegate4.callSegueFromCell2(myData: myData)
        mStats.mainController?.callSegueFromCell2(myData: myData)
    }

感谢任何指导。

【问题讨论】:

    标签: swift uitableview delegates segue programmatically


    【解决方案1】:
    let pendingCell = pendingNotificationCustomCell()
    

    看起来很奇怪。

    您应该在tableView(cellForRow:at:) UITableViewDataSource 方法中设置您的单元格。

    【讨论】:

    • 谢谢。这有点奇怪好吧。主表自定义单元格使用界面生成器设置并链接到自定义类。 pendingNotificationCustomCell() 用于以编程方式创建新的 TableView 和相关单元格。该类包含自己的 tableView(cellForRow:at) 函数,用于创建出现在此 TableView 上的单元格和标题。
    • 感谢这个 Ihar,因为它指导我再次查看该区域!
    【解决方案2】:

    与在单元格上设置委托而不将其传递给节标题有关的问题。我最终解决了以下问题:

    我在 MainViewController 中实现了一个名为 API_Segue_01 的函数和委托

    final class MainTableViewController: UITableViewController, API_Segue_01 {
    
    
        func API_Segue_01(myData dataobject: AnyObject) {
            navigationItem.backBarButtonItem = UIBarButtonItem(title: "Back", style: .plain, target: nil, action: nil)
            self.performSegue(withIdentifier: "showCreateNotificationsViewController", sender:dataobject )
        }
        /// Rest of class code
        /// ...
    

    在自定义单元格中,我创建了一个标头原型来引用外部函数:

    protocol API_Segue_01 {
        func API_Segue_01(myData dataobject: AnyObject)
    }
    

    我定义了一个 var 来保存对自定义单元格中 MainTableViewController 的引用和关联的标题

    class pendingNotificationCustomCell: UITableViewCell, UITableViewDataSource, UITableViewDelegate {
    
        var funcCallTo: API_Segue_01!
        /// Rest of class code
        /// ...
        
    class PendingNotificationsHeader: UITableViewHeaderFooterView {
        
        var funcCallTo:API_Segue_01!
        /// Rest of class code
        /// ...
    

    在创建自定义单元格的实例时,我提供了对 MainTableViewController 的引用

        pendingCell.funcCallTo = mainTableViewController
    

    由于操作按钮位于单元格标题中,我在 viewForHeaderInSection 中传递了对 mainTableViewController 的引用,如下所示

    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        
        print("##### viewForHeaderInSection")
        
        let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: "pendingHeaderID") as! PendingNotificationsHeader
        
        header.funcCallTo = self.funcCallTo
        
        return header
    }
    

    然后我可以使用这个引用来调用 API_Segue_01 函数

    @IBAction func createNewPriceAlertButtonPressed(_ sender: Any) {
        print ("##### New Price Alert Label Pressed")
        // Get the view
        
        var mydata = self /
    
        funcCallTo.API_Segue_01(myData: mydata)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多