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 UILabel
s of UITableViewCell
do change accordingly. This should not happen, should it?
What exactly is the purpose of adjustsFontForContentSizeCategory
and how can I prevent UITableViewCell
s labels from changing their font size?
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
}