skip to Main Content

I have a view controller that contains a table view and displays custom cells. I’m trying to react to a content size category change using the traitCollectionDidChange method (within the cell subclass), but this method is never called for the cells when this trait changes. On the other hand, it does get called when the size class changes.

traitCollectionDidChange is called for the view controller (when the content size category changes) and I can manually propagate the call to the visible cells, but it feels like extra work. Why is it not getting called for the cell subclasses specifically for the content size category change?

Edit for reasoning why I want the call within the cell:

I want to change the cell’s label to multi-line when the content size category is associated with accessibility, but keep it single-line otherwise. I’ve noticed this behavior in certain iOS apps, e.g. Apple Music.

2

Answers


  1. Any place in your app that needs to hear about content size category changes can register for the UIContentSizeCategory.didChangeNotification.

    https://developer.apple.com/documentation/uikit/uicontentsizecategory/1622948-didchangenotification

    So instead of you propagating the information down the hierarchy, just have an appropriate object register for that notification. For example, perhaps you have (or could have) a custom table view cell subclass where this would be appropriate.


    As for the question you actually asked, all I can do is provide a theory. Apple configures things like a UILabel to receive UIContentSizeCategory.didChangeNotification when it is in a table view cell. This involves some hanky-panky behind the scenes. I suspect that as part of this hanky-panky, they deliberately prevent the cell itself from receiving traitCollectionDidChange for content size category changes, since the same signal is arriving already in a different way and they don’t want to bombard the cell contents with too many events.

    Login or Signup to reply.
  2. A surprising detail about a UITableViewCell lifecycle:

    • changes in size class cause a call to traitCollectionDidChange(_:)

    • changes in size category recycle the cell, and traitCollectionDidChange(_:) is not called

    Therefore, changing the layout in response to size class and category needs code in two places:

    • traitCollectionDidChange(_:) for size class changes
    • initializer of the cell for size category changes

    You can confirm that the cell is recycled with a breakpoint in the delegate method tableView(_:willDisplay:forRowAt:), and also by noting that previous constraints conditionally set for the category disappear (because the cell is removed from its superview).

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search