iOS 10 中的 adjustsFontForContentSizeCategory 的用途是什么?

What is the purpose of adjustsFontForContentSizeCategory in iOS 10?

我在标准 UITableViewCelltextLabel 上设置 adjustsFontForContentSizeCategory。当我转到“设置”、“常规”、“辅助功能”、“更大的文本”以更改字体大小然后返回到我的应用程序时,UITableViewCellUILabels 会相应地发生变化。这不应该发生,对吗?

adjustsFontForContentSizeCategory 的确切用途是什么?如何防止 UITableViewCell 标签更改字体大小?

基本上adjustsFontForContentSizeCategory 动态改变 UILabel 的字体大小。

在我们获得 table 观看次数之前,让我们讨论一下 adjustsFontForContentSizeCategory。这样做的目的是控件会自动为我们调整字体。在此之前,您必须为 UIContentSizeCategory.didChangeNotification(以前称为 UIContentSizeCategoryDidChangeNotification)手动添加观察者。

因此,例如,在 Swift 3 中,在 10 之前的 iOS 版本中,为了在用户更改其首选字体大小时更新字体,我们必须做类似的事情:

class ViewController: UIViewController {

    @IBOutlet weak var dynamicTextLabel: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()

        dynamicTextLabel.font = .preferredFont(forTextStyle: .body)

        NotificationCenter.default.addObserver(forName: UIContentSizeCategory.didChangeNotification, object: nil, queue: .main) { [weak self] notification in
            self?.dynamicTextLabel.font = .preferredFont(forTextStyle: .body)
        }
    }

    deinit {
        NotificationCenter.default.removeObserver(self, name: UIContentSizeCategory.didChangeNotification, object: nil)
    }
}

在iOS10中,我们可以使用adjustsFontForContentSizeCategory,不再需要观察者,将上面的简化为:

class ViewController: UIViewController {

    @IBOutlet weak var dynamicTextLabel: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()

        dynamicTextLabel.font = .preferredFont(forTextStyle: .body)
        dynamicTextLabel.adjustsFontForContentSizeCategory = true
    }
}

好吧,话虽如此,table 次观看会自动观察到 UIContentSizeCategoryDidChangeNotification。您是否看到文本大小调整取决于是否在单元格标签上使用了动态类型。如果您使用动态文本,如下所示,您会看到 table 随着系统首选字体大小的变化而更新(不使用 adjustsFontForContentSizeCategory):

class ViewController: UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // make sure the cell resizes for the font with the following two lines

        tableView.estimatedRowHeight = 44
        tableView.rowHeight = UITableViewAutomaticDimension
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1000
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        cell.textLabel?.font = .preferredFont(forTextStyle: .body)
        // cell.textLabel?.adjustsFontForContentSizeCategory = true
        cell.textLabel?.text = "Row \(indexPath.row)"
        return cell
    }
}

如您所见,我唯一要做的就是将字体设置为动态文本,table 会自动适当更新。根据我的经验,在 table 视图中,不需要 adjustsFontForContentSizeCategory (看起来 table 视图必须观察必要的通知,它本身),但如果你总是可以设置它不要遇到那种自动调整大小的行为。

如果您明确不希望 table 视图单元格标签的字体发生变化,那么就不要使用动态文本,例如:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
    cell.textLabel?.font = .systemFont(ofSize: 17)
    cell.textLabel?.text = "Row \(indexPath.row)"
    return cell
}

动态类型仅适用于已实现 text styles.

的文本

因此,如果您总是想禁用动态类型并在单元格中显示相同大小的类型,请不要在其中使用文本样式或image size adjustment

正如@User511 和@Rob 所解释的那样,属性 adjustsFontForContentSizeCategory 告诉系统 自动处理它所属对象的动态类型 (当然要用文字样式).

当您使用设置更改内容大小时,table 视图单元格不需要最新的 属性,这要归功于它们的 self-sizing feature。这就是为什么您注意到此行为,而您没有明确执行此目的的原因。