为什么UIFont(descriptor:size :)比UIFont(name:size :)慢x200?

Alv*_*ivi 2 iphone ios

最近,我注意到滚动的性能正在降低。我找到了问题所在,发现原因是使用了UIFont(descriptor:size :)构造函数创建的字体。我更改了UIFont(name:size :)的构造函数,并解决了我的问题。

我在一个项目中隔离了问题。代码是:

import UIKit

class ViewController: UIViewController {
  @IBOutlet weak var firstLabel: UILabel!
  @IBOutlet weak var secondLabel: UILabel!

  @IBAction func onStartTest(sender: AnyObject) {
    startMeasurement()
    let firstFont = UIFont(name: "Marker Felt", size: 16)
    firstLabel.font = firstFont
    finishMeasurement("UIFont(name)")

    startMeasurement()
    let secondFontDescriptor = UIFontDescriptor(name: "Marker Felt", size: 16)
    let secondFont = UIFont(descriptor: secondFontDescriptor, size: 16)
    secondLabel.font = secondFont
    finishMeasurement("UIFont(descriptor)")
  }
}

private var time: UInt64 = 0

public func startMeasurement() {
  time = mach_absolute_time()
}

public func finishMeasurement(name: String) {
  let duration = mach_absolute_time() - time
  print("* \(name) \(duration)ns")
}
Run Code Online (Sandbox Code Playgroud)

这些是我的一些测量:

iPhone 4S - iOS 9.0.2

* UIFont(name) 111,300ns
* UIFont(descriptor) 112,420,263ns

iPhone 6S - iOS iOS 9.2

* UIFont(name) 134,247ns
* UIFont(descriptor) 17,047,707ns

Simulator - iOS 9.2

* UIFont(name) 1,971,106ns
* UIFont(descriptor) 485,208,205ns

Simulator - iOS 8.1

* UIFont(name) 9,946,584ns
* UIFont(descriptor) 1,957,802,431ns
Run Code Online (Sandbox Code Playgroud)

难道我做错了什么?

Sir*_*ens 6

我在WWDC 2018上问了一位工程师,他基本上是这样告诉我的:

描述符非常昂贵,因为它们每次都在ENTIRE系统字体库中搜索您提供的特征。他告诉我,此搜索实际上并未进行优化,因此切勿在滚动情况下使用,并且实际上仅应调用一次然后缓存。之所以这样做,是因为您实际上不需要指定字体名称,而只需指定各种字体名称,系统就会为您提供一些信息。

UIFont(name: size:)但是很快,因为它直接转到系统中要求的字体。它知道字体在哪里,因为您已经给出了完整的确切名称,然后就可以对其进行缩放。没有其他不错的功能。

大约是O(n)运算与O(1)