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

Swift Flow中UITableView隐藏/显示与重载时序不一致问题咨询

问题根因

  • 你对UIKit的渲染机制理解有偏差:所有UI属性(比如isHidden)的修改不会立刻触发屏幕渲染,只是标记为「待更新」,系统会等到当前主线程RunLoop的绘制周期才会批量提交给渲染服务。你在设置隐藏后,后续的UserDefaults读写、导航栏按钮配置、以及主队列async闭包里的同步逻辑如果耗时较长,都会卡住主线程,推迟隐藏状态的渲染时机,甚至会出现「隐藏」和「后续的显示」操作被合并,导致你完全看不到隐藏的过程。
  • 你当前把数据解析、表格重载逻辑全部放在主队列同步执行,如果finalParse涉及大量数据处理,会直接阻塞主线程,进一步放大时序问题。

修复方案

  1. 拆分耗时逻辑到后台线程,避免阻塞主线程UI更新
  2. 确保隐藏状态渲染完成后再执行数据加载逻辑,可以用极小的延时保证当前RunLoop的UI更新先完成
  3. 所有UI相关操作(包括表格重载、显示隐藏)必须放回主线程执行

修改后参考代码

@objc func sportsChange() {
    reloadTab = 1
    spinnerView.isHidden = false
    self.rosterTable.isHidden = true
    self.searchBar.isHidden = true
    
    // 先处理不需要耗时的UI配置和偏好存储
    if(selectedSport == fbSport){
        theUserDefaults.set(bbSport, forKey: "sportDefault")
        selectedSport = theUserDefaults.string(forKey: "sportDefault")
        sportLogo = sportBbLogo
        theUserDefaults.set(sportBbLogo, forKey: "sportLogo")
    } else if(selectedSport == bbSport){
        theUserDefaults.set(fbSport, forKey: "sportDefault")
        selectedSport = theUserDefaults.string(forKey: "sportDefault")
        theUserDefaults.set(sportFbLogo, forKey: "sportLogo")
        sportLogo = sportFbLogo
    }
    let sportImageSet = UIImage(named: sportLogo!)
    sportsIcon.setImage(sportImageSet , for: .normal)
    let sportButton = UIBarButtonItem(customView: sportsIcon)
    let currWidth = sportButton.customView?.widthAnchor.constraint(equalToConstant: 30)
    currWidth?.isActive = true
    let currHeight = sportButton.customView?.heightAnchor.constraint(equalToConstant: 30)
    currHeight?.isActive = true
    sportsIcon.addTarget(self, action: #selector(sportsChange), for: .touchUpInside)
    
    // 极小延时保证当前UI更新(隐藏表格、搜索栏)先渲染完成
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
        // 耗时的URL拼接、数据解析丢到后台队列
        DispatchQueue.global().async {
            self.rosterUrl = getRosterUrl(server: server, tid: teamid, yr: currentYearStr, sp: selectedSport!)
            self.finalParse(getTheUrl: self.rosterUrl)
            
            // 表格重载、UI显示切回主线程
            DispatchQueue.main.async {
                self.rosterTable.reloadWithAnimation()
                self.rosterTable.isHidden = false
                self.searchBar.isHidden = false
                self.spinnerView.isHidden = true
            }
        }
    }
}

额外注意点

  • 不要在主线程执行任何非UI的耗时操作,包括大量数据解析、文件读写、网络请求(看起来你当前的finalParse是同步请求/解析,非常容易卡主线程)
  • 避免强制解包sportLogo!这类可选值,增加判空逻辑减少崩溃风险

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 08:18:03