UISegmentedControl切换UITableView空白且崩溃问题排查修复求助
修复UISegmentedControl切换UITableView时空白及崩溃问题
问题根源
- 未响应分段控件切换事件:原代码没有给
segmentedController绑定值变更处理方法,切换分段时表格无法触发更新 - Cell注册逻辑错误:仅在
viewDidLoad中注册当前选中分段的Cell,切换到另一分段时对应Cell未注册,调用dequeueReusableCell会直接崩溃 - 无序字典的隐患:Swift的
Dictionary是无序集合,直接通过Array(priceDictionary.keys)获取的数组顺序不固定,可能导致显示混乱,极端场景下存在索引越界风险 - 切换时未触发表格刷新:即使注册了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
相关产品推荐
相关产品推荐

