Как получить пользовательский UITableViewCell, чтобы подобрать пользовательские изменения в предпочтительный размер текста?
Я работаю над простым приложением для отображения элементов в виде таблицы. Если я вернусь обычный UITableViewCell
объект из 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];
... тогда взаимодействие с динамическим текстом работает как положено; если пользователь идет в Settings | General | Text Size
, изменяет значение ползунка и затем возвращается в мое приложение, все видимые ячейки немедленно обновляются, чтобы использовать новый размер шрифта.
Если, однако, я возвращаю пользовательский подкласс UITableViewCell, где XIB содержит UILabel
который установлен для использования стиля текста вместо системного шрифта, тогда динамический текст не работает должным образом. Вот код, который я использую, чтобы назначить XIB для таблицы в viewDidLoad
:
[self.table registerNib:[UINib nibWithNibName:@"EmailCell"
bundle:[NSBundle mainBundle]]
forCellReuseIdentifier:@"EmailCell"];
а затем этот код в tableView:cellForRowAtIndexPath:
static NSString *cellIdentifier = @"EmailCell";
EmailCell *cell = (EmailCell *)[tableView
dequeueReusableCellWithIdentifier:cellIdentifier];
При первом запуске приложения отображаются видимые ячейки с размером текста, который соответствует выбранному пользователем предпочтительному размеру текста. Однако если я затем перейду к настройкам и изменим этот размер, а затем вернусь к своему приложению, все видимые ячейки останутся с прежним размером текста. Если я затем прокручиваю вверх, я вижу две ячейки, которые показывают новый (правильный) размер текста, но остальные все еще остаются старыми. Если я остановлю и перезапущу приложение, все ячейки появятся с новым (правильным) размером текста.
Мне кажется очевидным, что табличное представление хранит ячейки предыдущего размера в очереди и не обновляет автоматически их размер шрифта в ответ на изменение пользователем предпочтительного размера текста. Но я не понимаю, почему табличное представление делает это изменение автоматически, когда очередь содержит обычные не подклассы UITableViewCell
экземпляров. Есть ли способ заставить это работать без перезапуска приложения (или без воссоздания UITableView
экземпляр, тем самым опустошая очередь)? Есть ли способ программно (и юридически) очистить эту очередь?
Изменить: в случае, если кто-то заинтересован в этой проблеме, мое исправление для этого было написать общий метод утилиты, который создает новое представление таблицы, копирует все соответствующие свойства из исходного представления таблицы (включая зарегистрированные классы ячеек), а затем меняет местами новый для старого. Так как это новая таблица, она генерирует все новые экземпляры ячеек в очереди, которые включают новый размер текста.
3 ответа
Это теперь обрабатывается для вас в iOS 10.
http://useyourloaf.com/blog/auto-adjusting-fonts-for-dynamic-type/
Задавать adjustsFontForContentSizeCategory
в YES
/ true
на вашем ярлыке, и он автоматически изменит свой размер при изменении размера текста.
Исходя из того, что вы описали, может показаться, что вы просто хотите перезагрузить таблицу каждый раз, когда представление возвращается на экран после того, как пользователь задал его фон. Чтобы добиться этого, как я думаю, вам нужно, вам нужно добавить в метод init следующее для вашего tableView - он скажет вашему tableView правильно перезагрузить ячейки всякий раз, когда приложение собирается выйти на передний план:
[[NSNotificationCenter defaultCenter] addObserver:self.tableView selector:@selector(reloadData) name:UIApplicationWillEnterForegroundNotification object:nil];
Таким образом, если пользователь возвращается к представлению, открывая приложение после перехода к настройкам телефона, ваш tableView должен перезагрузиться, и изменения (если они были сделаны) должны быть правильно отражены.
Вы можете увидеть быстрое видео результата, который я протестировал здесь:
https://www.dropbox.com/s/pvjuiyofydnxnvd/textsize.mov
РЕДАКТИРОВАТЬ:
Как вы сказали в предыдущем комментарии, может показаться, что с вашей реализацией пера что-то не так. Разница лишь в том, где / как вы обновляете свойство метки. В пользовательской ячейке я создал свойство метки и свойство шрифта и добавил метку к ячейке в init, а в layoutSubviews переопределил шрифт. Вот код:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
LabelCell *cell = [tableView dequeueReusableCellWithIdentifier:@"LabelCell"];
if (cell == nil) {
cell = [[LabelCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"LabelCell"];
}
cell.myLabel.text = _items[indexPath.row];
cell.myFont = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline];
return cell;
}
И в самой клетке
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
self.myLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, self.contentView.frame.size.width - 20, 34)];
self.myLabel.backgroundColor = [UIColor greenColor];
[self.contentView addSubview:self.myLabel];
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
self.myLabel.font = self.myFont;
}
И вот тот же результат, используя пользовательские ячейки с метками:
https://www.dropbox.com/s/ow2zkb6j9yq2c3m/labelcells.mov
Что касается "очистки очереди", то ячейки не ставятся в очередь до тех пор, пока они не появятся на экране, вы можете увидеть это, зарегистрировав значение счетчика сразу после удаления ячейки из очереди с идентификатором. Если сейчас на экране 10 ячеек, он удаляет только 10 ячеек. Это причина, по которой вы используете код if (! Cell) {здесь делаете вещи, которые являются общими для всех ячеек}, а затем вы делаете вещи, специфичные для каждой ячейки, и почему этот код работает, даже если вы предполагаете, что reloadData не "очистить очередь", что я не уверен, что это все равно не произойдет после прочтения документации UITableView.
Мое исправление для этого состояло в том, чтобы написать общий служебный метод, который создает новое табличное представление, копирует все соответствующие свойства из исходного табличного представления (включая зарегистрированные классы ячеек), а затем заменяет новое на старое. Так как это новая таблица, она генерирует все новые экземпляры ячеек в очереди, которые включают новый размер текста.