TableView进行seguing并导致意外返回nil

时间:2017-08-25 18:30:24

标签: ios swift uitableview storyboard segue

这是我目前的设置:

MainMenuViewController - > SubMenuViewController - > UserInputViewController - > ResultViewController

我的所有视图控制器都包含tableView

当用户点按MainMenuViewControlle中的单元格时,它将转到SubMenuViewController。一切都很好,花花公子。

这里变得棘手,在SubMenuViewController中,有些单元需要实例化另一个SubMenuViewController,因为子菜单选项可能有几个级别。

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        guard let selectedNode = node?.childenNode[indexPath.row] else {
            return
        }

        if selectedNode.isLeaveNode() {
            performSegue(withIdentifier: "userInput", sender: self)
        } else {
            let subMenuViewController = SubMenuViewController(node: selectedNode)
            self.navigationController?.pushViewController(subMenuViewController, animated: true)
        }

当没有子节点时,它将转换为UserInputViewController,但是当有更多选项时,它需要实例化另一个SubMenuViewControllertableView将填充基于用户之前已点击过的单元格,直到selectedNode.isLeaveNode()为真(这意味着不会有任何子节点)。

此代码运行时出现此问题:

    let subMenuViewController = SubMenuViewController(node: selectedNode)
    self.navigationController?.pushViewController(subMenuViewController, animated: true)

它给我以下错误:

  

致命错误:在解包可选值时意外发现nil

我在这里注册了我的单元格:

let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: "SubMenuTableViewCell", bundle: bundle)
tableView.register(nib, forCellReuseIdentifier: "SubMenuCell")

我的所有tableView单元格都是使用xib文件实例化的,我在viewDidLoad()

中注册了我的单元格

有人能看到问题吗?

更新

以下是我的其余代码:

UIViewController

class SubMenuViewController: UIViewController {

    var node: Node?

    init(node: Node) {
        self.node = node
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    @IBOutlet weak var tableView: UITableView!

    override func viewDidLoad() {

        super.viewDidLoad()

        self.navigationController?.isNavigationBarHidden = false
        self.navigationItem.title = node?.value.rawValue

        let bundle = Bundle(for: type(of: self))
        let nib = UINib(nibName: "SubMenuTableViewCell", bundle: bundle)
        tableView.register(nib, forCellReuseIdentifier: "SubMenuCell")
    }
}

UITableViewDataSource

extension SubMenuViewController: UITableViewDataSource {

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return node!.childCount
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        print("called")

        let cell = tableView.dequeueReusableCell(withIdentifier: "SubMenuCell", for: indexPath) as! SubMenuTableViewCell
        let desciptionModule = node?.childenNode[indexPath.row].value

        let description = Modules.description(module: desciptionModule!)

        cell.title.text = description.main
        cell.subtitle.text = description.sub

        return cell

    }
}

UITableViewDelegate

extension SubMenuViewController: UITableViewDelegate {
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 68
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        guard let selectedNode = node?.childenNode[indexPath.row] else {
            return
        }

        if selectedNode.isLeaveNode() {
            performSegue(withIdentifier: "userInput", sender: self)
        } else {
            let subMenuViewController = SubMenuViewController(node: selectedNode)
            self.navigationController?.pushViewController(subMenuViewController, animated: true)
        }

    }  
}

2 个答案:

答案 0 :(得分:0)

appBar: new PreferredSize( child: new Hero( tag: AppBar, child: new AppBar( leading: const BackButton(), title: new Text('Flutter Logo'), ), ), preferredSize: new AppBar().preferredSize, ), 方法中,请务必执行以下操作:

根据您发布的代码,您可能会遇到以下问题:

viewDidLoad()

我建议将其替换为以下行:

let bundle = Bundle(for: type(of: self))

let bundle = Bundle(forClass: self)

如果您仍然遇到此问题,请尝试修改以下代码行:

let bundle = Bundle.main

let nib = UINib(nibName: "SubMenuTableViewCell", bundle: bundle)

let nib = UINib(nibName: "SubMenuTableViewCell", bundle: nil) tableView:cellForRowAtIndexPath方法中,请添加以下内容:

UITableViewControllerDelegate

注意

  1. 确保UITableViewCell的reuseIdentifier是" SubMenuCell"
  2. 确保SubMenuTableViewCell.xib文件的所有者为var cell = tableView.dequeueReusableCellWithIdentifier("SubMenuCell") as? UITableViewCell if cell == nil { tableView.registerNib(UINib(nibName: "SubMenuTableViewCell", bundle: nil), forCellReuseIdentifier: "SubMenuCell") cell = tableView.dequeueReusableCellWithIdentifier("SubMenuCell") as SubMenuTableViewCell! } cell.configure(data: data[indexPath.row]) tableView.reloadData() return cell
  3. 确保模块没有说"无" (即模块应该是项目目标的名称)。
  4. 请务必在SubMenuTableViewCell功能中致电tableView.reloadData()

答案 1 :(得分:0)

问题解决了

问题在于我将视图控制器实例化错误。这一行:

let subMenuViewController = SubMenuViewController(node: selectedNode)

只返回没有出口的原始对象,这就是为什么我得到可选的nil错误,因为没有tableView可以开始。

正确的方法是使用故事板实例化它。每个视图控制器都有一个storyboard属性作为可选项,因为我的视图控制器存在于一个故事板中,该属性不会为零。

而不是这样做:

let subMenuViewController = SubMenuViewController(node: selectedNode)
self.navigationController?.pushViewController(subMenuViewController, animated: true)

我实际上需要这样做:

let subMenuViewController = storyboard!.instantiateViewController("SubMenuViewController") 

这样我就知道我的subMenuViewController将包含我的tableView属性,它是来自storyboard的IBOutlet。