问题描述:
进入一个带有时间选择器的页面,使用模拟器时需要等待10s
左右的时间,使用真机需要1s
左右的时间,运行过程中查看内存
和CPU
,发现CPU
暴涨,内存
也上涨。此行为很影响用户体验,所以需要解决这个问题。
前提:
要做一个页面显示时间,效果图如下:
因为要做到类似于无限循环的效果所以数据源设置为了
小时( 24 * 10)
分钟(60 * 10)
坑点:
因为要自定义文字颜色,所以就使用了下面这个代理方法
func pickerView(_ pickerView: UIPickerView, attributedTitleForRow row: Int, forComponent component: Int) -> NSAttributedString? {
return NSAttributedString(string: "test",
attributes: [
NSAttributedString.Key.foregroundColor: UIColor.white, //白色文字
NSAttributedString.Key.textEffect:
NSAttributedString.TextEffectStyle.letterpressStyle
])
}
看起来代码都很正常,因为之前并没有使用模拟器运行,所以这个问题不是很明显(真机效果会好很多),直到今天使用了模拟器运行,点一下emmmm,可以停顿给十几秒。然后就开始了一通查找。
如何定位的:
先是把多余的代码通通注释,定位是
UI
问题还是其他问题定位到
UI
之后,把部分UI
代码注释掉,定位到具体UI
然后就定位到
pickerView
,继续查看其他的代码,猜测可能是因为数据源量过大引起改小数据量之后,稍微好转, 但还是有问题,怀疑复用问题
-
然后就发现上面的这个代理并没有复用问题,怀疑
NSAttributedString
创建出了问题,于是把代理改为了func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { return "test" }
-
发现速度立马恢复,于是定位到
NSAttributedString
后查阅资料得知
NSAttributedString.TextEffectStyle.letterpressStyle
这个东西会给字体加上阴影和高光,所以CPU
在处理的时候需要耗费大量资源。
解决方案:
- 1 使用另外的代理方法
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return "test"
}
上述方法可以优化性能,但是字体颜色并未修改,所以优先级低
- 2 把
NSAttributedString.TextEffectStyle.letterpressStyle
效果去掉
func pickerView(_ pickerView: UIPickerView, attributedTitleForRow row: Int, forComponent component: Int) -> NSAttributedString? {
return NSAttributedString(string: "test",
attributes: [
NSAttributedString.Key.foregroundColor: UIColor.white
])
}
上述修改方案可以解决该问题,优先级高
- 3 在换一个代理方法
func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView { .... return View; }
上述修改方案可以解决该问题,优先级高