You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift开发调用didMove(toParent)后tableView不显示且空值报错如何解决

问题描述

WalletViewController中的tableView始终无法显示,导航栏按钮也不生效,怀疑问题和调用didMove(toParent)方法添加子控制器的逻辑相关。需要实现一个可向个人资料添加新银行卡的页面,无论是纯代码编写还是使用storyboard实现,都会抛出错误:Unexpectedly found nil while implicitly unwrapping an Optional value。

问题根因
  1. 子控制器缺少导航栏上下文:WalletViewController作为子控制器被直接添加到BeginViewController的视图上,本身没有嵌套在UINavigationController中,导致navigationItem、navigationController均为nil,导航栏按钮无法生效,调用导航控制器相关方法时还会触发隐式解包崩溃。
  2. 表格数据未刷新:从UserDefaults读取银行卡数据后,没有调用tableView.reloadData()刷新表格,导致tableView始终无内容展示。
  3. 硬编码布局适配问题:Add按钮的frame被硬编码为y=700,小屏设备上会超出可视区域,且tableView没有做自适应约束,父视图大小变化时会出现布局错位。
  4. 控制器初始化逻辑冲突:加卡页addCardViewController同时存在storyboard初始化和纯代码初始化两种逻辑,如果addCardViewController是用storyboard搭建的,纯代码init会导致内部IBOutlet为nil,触发崩溃。
修复步骤
  • 给所有功能子控制器套上导航容器,修改BeginViewController中的子控制器声明:
// 将原有声明替换为以下格式,其他Profile、MyBookings等控制器同理套UINavigationController
private let WalletController = UINavigationController(rootViewController: WalletViewController())
  • 修改WalletViewController的viewDidLoad逻辑,加载数据后刷新表格:
override func viewDidLoad() {
    super.viewDidLoad()
    addTable()
    // 新增两行代码,加载已存储的银行卡数据并刷新表格
    updateCard()
    tableView.reloadData()
    
    view.backgroundColor = UIColor(named: "RED")
    button.setTitle("Add New Card", for: .normal)
    button.backgroundColor = UIColor(named: "yellow-2")
    button.setTitleColor(UIColor(named: "RED"), for: .normal)
    button.layer.cornerRadius = 15
    button.addTarget(self, action: #selector(didTapAddButton), for: .touchUpInside)
    
    // 不需要导航栏右上角按钮可直接删除以下逻辑,避免nil风险
    if !UserDefaults().bool(forKey: "setup") {
        UserDefaults().set(true, forKey: "setup")
        UserDefaults().set(0, forKey: "count")
        navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Add New Card", style: .plain, target: self,
        action: #selector(didTapAdd))
    }
}
  • 替换硬编码frame为自动布局,适配不同屏幕尺寸:
func addTable() {
    tableView.translatesAutoresizingMaskIntoConstraints = false
    tableView.delegate = self
    tableView.dataSource = self
    tableView.separatorStyle = .singleLine
    tableView.register(UITableViewCell.self, forCellReuseIdentifier: "addCard")
    self.view.addSubview(tableView)
    
    button.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(button)
    
    NSLayoutConstraint.activate([
        tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
        tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
        tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
        tableView.bottomAnchor.constraint(equalTo: button.topAnchor, constant: -20),
        
        button.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 25),
        button.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -25),
        button.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -20),
        button.heightAnchor.constraint(equalToConstant: 50)
    ])
}
  • 优化updateCard方法,避免重复加载数据,加载完成后自动刷新表格:
func updateCard() {
    addNewCard.removeAll() // 清空旧数据避免重复
    guard let count = UserDefaults().value(forKey: "count") as? Int else {
        return
    }
    for x in 0..<count {
        if let addCard = UserDefaults().value(forKey: "addCard\(x+1)") as? String {
           addNewCard.append(addCard)
       }
    }
    tableView.reloadData() // 自动刷新表格
}
  • 统一addCardViewController的初始化方式,要么全部用storyboard初始化,要么全部用纯代码初始化,避免混合使用导致IBOutlet隐式解包崩溃。

内容的提问来源于stack exchange,提问作者Charles Morgan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 07:54:08