iOS Swift UISegmentedControl自定义字体跨视图返回还原问题排查
异常根源与修复方案
核心问题定位
- 你目前把自定义字体、颜色的配置全部写在
UISegmentedControl.appearance()全局外观代理上,没有把这些配置绑定到具体的分段控件实例本身。UIAppearance代理的生效有时序硬要求:只有控件在配置代码执行完成后才初始化进入视图层级,配置才会生效。而你把这些零散的配置写在每个页面的setupSegmentControl方法里,当从其他页面返回原页面时,系统会触发表视图组头的重渲染、控件重挂载,此时外观代理的配置不会介入这次重渲染流程,分段控件的标签字体就会被重置为系统默认值。 - 你在
viewForHeaderInSection代理方法中,每次触发都会新建一个空的组头视图,再把之前创建好的同一个分段控件实例反复通过addSubview挂到新的组头视图上。iOS系统中,已经有父视图的控件被重新挂载到新父视图时,会自动触发全量外观状态的重计算。因为你没有给这个分段控件实例本身绑定自定义字体属性,全靠全局外观代理兜底,就很容易出现属性覆盖、样式丢失的问题。
具体修复步骤
- 删掉所有零散位置对
UISegmentedControl.appearance()的赋值代码。如果需要做全局统一样式配置,就把这些配置统一挪到App启动的最早阶段(比如AppDelegate的启动完成回调),保证所有分段控件完成初始化前,全局样式配置已经加载完毕,不会出现时序错位。 - 把原来通过appearance代理设置的字体、颜色,直接调用
setTitleTextAttributes(_:for:)方法绑定到你当前创建的segmentedControl实例上。实例自身存储的属性是持久生效的,不会因为视图重挂载、页面切回被系统自动重置。对应代码修改参考:// 替换原有的全局appearance配置,直接给当前分段控件实例设置属性 segmentedControl.setTitleTextAttributes([ .foregroundColor: UIColor(displayP3Red: 0/255, green: 0/255, blue: 0/255, alpha: 1), .font: UIFont(name: "Cabin-SemiBold", size: 16)! ], for: .selected) segmentedControl.setTitleTextAttributes([ .foregroundColor: UIColor(displayP3Red: 138/255, green: 145/255, blue: 172/255, alpha: 0.7), .font: UIFont(name: "Cabin-SemiBold", size: 16)! ], for: .normal) - 优化组头视图的复用逻辑,不要每次
viewForHeaderInSection触发时都新建空组头再把分段控件加进去。可以在第一次方法触发时就把分段控件添加到组头视图上并做缓存,后续触发时代码直接返回缓存好的组头视图,减少不必要的视图重挂载、外观重渲染流程。
内容的提问来源于stack exchange,提问作者Jabi
相关产品推荐
相关产品推荐

