iosuitableviewdynamic-text

How to get custom UITableViewCell to pick up user changes to preferred text size?


I'm working on a simple app to display items in a table view. If I return an ordinary UITableViewCell object from tableView:cellForRowAtIndexPath:

static NSString *cellIdentifier = @"EmailCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:
    cellIdentifier];

if (!cell) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
        reuseIdentifier:@"EmailCell"];
}

cell.textLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline];

... then the interaction with Dynamic Text works as expected; if the user goes to Settings | General | Text Size, changes the slider value and then returns to my app, all of the visible cells immediately update themselves to use the new font size.

If, however, I return a custom subclass of UITableViewCell, where the XIB contains a UILabel that is set to use a Text Style instead of a System Font, then the Dynamic Text does not work properly. Here is the code I'm using to assign the XIB to the table in viewDidLoad:

[self.table registerNib:[UINib nibWithNibName:@"EmailCell"
                                           bundle:[NSBundle mainBundle]]
     forCellReuseIdentifier:@"EmailCell"];

and then this code in tableView:cellForRowAtIndexPath:

static NSString *cellIdentifier = @"EmailCell";
EmailCell *cell = (EmailCell *)[tableView 
    dequeueReusableCellWithIdentifier:cellIdentifier];

When I first run the app, the visible cells appear with a text size that matches the user's selected preferred text size. However, if I then go to settings and change that size and then go back to my app, all of the visible cells remain with the previous text size. If I then scroll up, I will see two cells that show the new (correct) text size but the rest are still the old size. If I stop and restart the app, all cells now appear with the new (correct) text size.

It seems apparent to me that the tableview is keeping the previously-sized cells in the queue and not automatically updating their font size in response to the user's change of preferred text size. But I'm not understanding why the tableview does make this change automatically when the queue contains ordinary non-subclassed UITableViewCell instances. Is there any way I can get this to work without restarting the app (or without recreating the UITableView instance, thereby emptying the queue)? Is there any way to programmatically (and legally) clear this queue?

Edit: in case anyone's interested in this problem, my drop-in fix for this was to write a general utility method that makes a new tableview, copies over all the relevant properties from the original tableview (included registered cell classes) and then swaps the new one for the old one. Since this is a new table, it generates all-new instances of the queued cells which incorporate the new text size.


Solution

  • This is now handled for you in iOS 10.

    http://useyourloaf.com/blog/auto-adjusting-fonts-for-dynamic-type/

    Set adjustsFontForContentSizeCategory to YES / true on your label and it'll resize itself automatically when the text size preference changes.