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

UISegmentedControl切换UITableView空白且崩溃问题排查修复求助

修复UISegmentedControl切换UITableView时空白及崩溃问题

问题根源

  1. 未响应分段控件切换事件:原代码没有给segmentedController绑定值变更处理方法,切换分段时表格无法触发更新
  2. Cell注册逻辑错误:仅在viewDidLoad中注册当前选中分段的Cell,切换到另一分段时对应Cell未注册,调用dequeueReusableCell会直接崩溃
  3. 无序字典的隐患:Swift的Dictionary是无序集合,直接通过Array(priceDictionary.keys)获取的数组顺序不固定,可能导致显示混乱,极端场景下存在索引越界风险
  4. 切换时未触发表格刷新:即使注册了Cell,没有主动调用tableView.reloadData(),表格也不会更新数据

修复方案及完整代码

class PriceViewController: UIViewController {

    // 改用有序数组存储数据,保证显示顺序固定
    let priceItems: [(name: String, price: String)] = [
        ("мини-тату", "2000-4000р"),
        ("перманент бровей", "4500р"),
        ("коррекция", "50% от тату"),
        ("коррекция пм бровей", "2500")
    ]

    let stockItems: [(name: String, desc: String)] = [
        ("Скидка имениннику 20%", "Скидка действительна 3 дня до дня рождения и 3 дня после, при предъявлении оригинала документа, удостоверяющего личность. Скидка не распространяется на другие акции."),
        ("Две и более мини-тату со скидкой 30%", "Скидка предоставляется при оформлении записи на 2 и более мини-тату за один сейчас."),
        ("Скидка для подружек", "Приведи подругу и получу скидку на следующую татуировку/перманент/коррекцию 15%.")
    ]

    @IBOutlet var sideMenuBtn: UIBarButtonItem!
    @IBOutlet weak var segmentedController: UISegmentedControl!
    @IBOutlet weak var tableView: UITableView! 

    override func viewDidLoad() {
        super.viewDidLoad()
        
        navigationController?.navigationBar.tintColor = .white
        self.sideMenuBtn.target = revealViewController()
        self.sideMenuBtn.action = #selector(self.revealViewController()?.revealSideMenu)
        
        tableView.delegate = self
        tableView.dataSource = self
        
        // 提前注册所有需要的Cell,避免切换时重复注册或未注册
        tableView.register(UINib(nibName: PriceCell.identifier, bundle: nil), forCellReuseIdentifier: PriceCell.identifier)
        tableView.register(UINib(nibName: StockCell.identifier, bundle: nil), forCellReuseIdentifier: StockCell.identifier)
        
        // 给分段控件绑定值变更事件
        segmentedController.addTarget(self, action: #selector(segmentedControlValueChanged), for: .valueChanged)
        
        // 初始化时加载默认分段数据
        tableView.reloadData()
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        self.revealViewController()?.gestureEnabled = false
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        self.revealViewController()?.gestureEnabled = true
    }

    // 分段控件值变更处理方法
    @objc private func segmentedControlValueChanged() {
        // 切换分段后刷新表格
        tableView.reloadData()
    }

    func loadCellPrice(indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: PriceCell.identifier, for: indexPath) as! PriceCell
        let item = priceItems[indexPath.row]
        cell.nameOfServiceLabel?.text = item.name
        cell.priceLabel?.text = item.price
        return cell
    }

    func loadCellStock(indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: StockCell.identifier, for: indexPath) as! StockCell
        let item = stockItems[indexPath.row]
        cell.nameStock?.text = item.name
        cell.descriptionStock?.text = item.desc
        return cell
    }
}

extension PriceViewController: UITableViewDelegate, UITableViewDataSource {

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        switch segmentedController.selectedSegmentIndex {
        case 0:
            return priceItems.count
        case 1 :
            return stockItems.count
        default:
            return 0
        }
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        switch segmentedController.selectedSegmentIndex {
        case 0:
            return loadCellPrice(indexPath: indexPath)
        case 1 :
            return loadCellStock(indexPath: indexPath)
        default:
            return UITableViewCell()
        }
    }
}

关键修改说明

  • 改用有序数组存储数据:替换原来的无序字典,保证单元格显示顺序固定,同时避免字典转数组的潜在问题
  • 提前注册所有Cell:在viewDidLoad中一次性注册PriceCell和StockCell,避免切换分段时因未注册Cell导致崩溃
  • 添加分段控件值变更事件:绑定segmentedControlValueChanged方法,切换分段时主动刷新表格
  • 简化数据访问逻辑:直接通过有序数组的索引获取数据,代码更简洁安全

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 06:01:05