Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the purpose of adjustsFontForContentSizeCategory in iOS 10?

I am setting adjustsFontForContentSizeCategory on a textLabel of a standard UITableViewCell. When I go to "Settings", "General", "Accessibility", "Larger Text" to change the font size and then back to my app, the UILabels of UITableViewCell do change accordingly. This should not happen, should it?

What exactly is the purpose of adjustsFontForContentSizeCategory and how can I prevent UITableViewCells labels from changing their font size?

like image 244
user1195883 Avatar asked Nov 09 '16 10:11

user1195883


1 Answers

Before we get to table views, let's discuss adjustsFontForContentSizeCategory. The purpose of that is that the control will automatically adjust the font for us. Prior to this, you'd have to manually add an observer for UIContentSizeCategory.didChangeNotification (previously called UIContentSizeCategoryDidChangeNotification).

So, for example, in Swift 3, in iOS versions prior to 10, in order to have the font update when the user changed their preferred font size, we'd have to do something like:

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)
    }
}

In iOS 10, we can use adjustsFontForContentSizeCategory and the observer is no longer needed, simplifying the above to:

class ViewController: UIViewController {

    @IBOutlet weak var dynamicTextLabel: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()

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

OK, that having been said, table views observe UIContentSizeCategoryDidChangeNotification automatically. Whether you see the text resizing is a product of whether dynamic type was used on the cell's label or not. If you use dynamic text, like below, you'll see the table update as the system's preferred font size changes (without using 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
    }
}

As you can see, the only thing I had to do was set the font to dynamic text, and the table automatically updated appropriately. In my experience, in table views, the adjustsFontForContentSizeCategory is not needed (it looks like the table view must be observing the necessary notification, itself), but you can always set it if you don't experience that auto-resizing behavior.

If you explicitly don't want the table view cell's label's font to change, then just don't use dynamic text, e.g.:

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
}
like image 76
Rob Avatar answered Nov 11 '22 19:11

Rob