将UILabel.attributedText设置为相同的值是否昂贵?

时间:2017-04-24 15:36:47

标签: ios swift uilabel

我的应用程序中有一个视图控制器,我用它来进行调试,以显示应用程序的一些内部结构(仅适用于本地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

    }
}

2 个答案:

答案 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%。也就是说,注意它可能需要很多标签才能真正成为瓶颈。还要记住(如果遇到一些疯狂的情况)这是你的瓶颈,这种优化只有在事先预先分配了属性字符串时才有效。