我的应用程序中有一个视图控制器,我用它来进行调试,以显示应用程序的一些内部结构(仅适用于本地xcode版本,应用程序商店版本没有此控制器)。
在这个控制器中,我有一个标签,我想反映内部组件的状态(具体来说,我希望它显示该组件是启用还是禁用)。
我的问题:
#1:将UILabel的.attributedText
属性设置为与以前相同的值是否很昂贵,还是应该缓存旧值并仅在更改时设置属性? /强>
#2:.text
(非归因)属性怎么样?
我目前正在使用以下代码:
// Schedule timer to update the control panel. (This is debug-only, so not worth
// the complexity of making this event-based)
Timer.scheduledTimer(withTimeInterval: 0.5,
repeats: true) { [weak self] timer in
DispatchQueue.main.async {
// Stop timer if we've been dealloced or are no longer being presented
guard let strongSelf = self,
strongSelf.isBeingPresented else
{
timer.invalidate()
return
}
// "Something Enabled / Disabled" label
let somethingIsEnabled = strongSelf.someDepenency.isEnabled
let somethingEnabledString = NSMutableAttributedString(string: "Something ")
somethingEnabledString.append(NSAttributedString(string: isEnabled ? "Enabled" : "Disabled",
attributes: isEnabled ? nil : [NSForegroundColorAttributeName: UIColor(xtHardcodedHexValue: "0xCD0408")]))
strongSelf.somethingEnabledLabel?.attributedText = somethingEnabledString
}
}
答案 0 :(得分:4)
在我分享一些数字之前,我强烈建议不要执行此类过早优化。请考虑以下代码:
private func getAttributedString() -> NSMutableAttributedString{
let attributedString = NSMutableAttributedString(string: "Something ")
attributedString.append(NSAttributedString(string: "Enabled",
attributes: [NSForegroundColorAttributeName: UIColor(rgb: 0xCD0408)]))
return attributedString
}
//overwrites attributed text 100000 times
@IBAction func overwriteAttributedText(_ sender: Any) {
let timeBeforeAction = Date.init()
print ("Time taken to overwrite attributed text is ")
for _ in 1 ... 100000{
label.attributedText = getAttributedString()
}
let timeAfterAction = Date.init()
let timeTaken = timeAfterAction.timeIntervalSince(timeBeforeAction)
print(timeTaken)
}
//overwrites attributed text 100 times
@IBAction func cacheAttributedText(_ sender: Any) {
let timeBeforeAction = Date.init()
print ("Time taken to selectively overwrite attributed text is ")
for i in 1 ... 100000{
if i % 1000 == 0 {
label.attributedText = getAttributedString()
}
}
let timeAfterAction = Date.init()
let timeTaken = timeAfterAction.timeIntervalSince(timeBeforeAction)
print(timeTaken)
}
//overwrites text 100000 times
@IBAction func overWriteText(_ sender: Any) {
let defaultText = "Hello World"
let timeBeforeAction = Date.init()
print ("Time taken to overwrite text is ")
for _ in 1 ... 100000{
label.text = defaultText
}
let timeAfterAction = Date.init()
let timeTaken = timeAfterAction.timeIntervalSince(timeBeforeAction)
print(timeTaken)
}
结果如下:
Time taken to overwrite attributed text is 0.597925961017609
Time taken to selectively overwrite attributed text is 0.004891037940979
Time taken to overwrite text is 0.0462920069694519
结果不言而喻,但如果需要进行这样的优化,我就把它留给你。
答案 1 :(得分:1)
虽然7to4在过早优化方面是正确的,但他使用的演示代码具有误导性。 .attributedText
setter本身实际上比设置.text
更快;创建属性字符串是瓶颈。这是他的代码的修改版本,其中包含预先缓存属性字符串的方法:
private func getAttributedString() -> NSMutableAttributedString{
let attributedString = NSMutableAttributedString(string: "Something ")
attributedString.append(NSAttributedString(string: "Enabled",
attributes: [NSAttributedStringKey.foregroundColor: UIColor.red]))
return attributedString
}
//overwrites attributed text 100000 times
@IBAction func overwriteAttributedText(_ sender: Any) {
let timeBeforeAction = Date.init()
print ("Time taken to overwrite attributed text is ")
for _ in 1 ... 100000{
label.attributedText = getAttributedString()
}
let timeAfterAction = Date.init()
let timeTaken = timeAfterAction.timeIntervalSince(timeBeforeAction)
print(timeTaken)
}
//overwrites attributed text 100000 times with a cached string
@IBAction func overwriteAttributedTextWithCachedString(_ sender: Any) {
let timeBeforeAction = Date.init()
let attributedString = getAttributedString()
print ("Time taken to overwrite attributed text with cached string is ")
for _ in 1 ... 100000{
label.attributedText = attributedString
}
let timeAfterAction = Date.init()
let timeTaken = timeAfterAction.timeIntervalSince(timeBeforeAction)
print(timeTaken)
}
//overwrites text 100000 times
@IBAction func overWriteText(_ sender: Any) {
let defaultText = "Hello World"
let timeBeforeAction = Date.init()
print ("Time taken to overwrite text is ")
for _ in 1 ... 100000{
label.text = defaultText
}
let timeAfterAction = Date.init()
let timeTaken = timeAfterAction.timeIntervalSince(timeBeforeAction)
print(timeTaken)
}
结果:
Time taken to overwrite attributed text is
0.509455919265747
Time taken to overwrite attributed text with cached string is
0.0451710224151611
Time taken to overwrite text is
0.0634149312973022
平均而言,.attributedText
setter本身比.text
setter快30~40%。也就是说,注意它可能需要很多标签才能真正成为瓶颈。还要记住(如果遇到一些疯狂的情况)这是你的瓶颈,这种优化只有在事先预先分配了属性字符串时才有效。