从 TableView 标头访问 UITableViewController 委托

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

我在从与以编程方式创建的 TableView 关联的 TableView 标头调用 segue 时遇到问题。作为权宜之计,我使用单例保存了对主 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
2个回答
0
投票
let pendingCell = pendingNotificationCustomCell()

看起来很奇怪。

你应该在

tableView(cellForRow:at:)
UITableViewDataSource 方法中设置你的单元格。


0
投票

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

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