2

我正在开发一个简单的应用程序来在表格视图中显示项目。如果我从以下位置返回一个普通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];

当我第一次运行该应用程序时,可见单元格的文本大小与用户选择的首选文本大小相匹配。但是,如果我然后转到设置并更改该大小,然后返回我的应用程序,则所有可见单元格都会保留以前的文本大小。如果我然后向上滚动,我将看到两个显示新(正确)文本大小的单元格,但其余的仍然是旧大小。如果我停止并重新启动应用程序,所有单元格现在都会以新的(正确的)文本大小显示。

在我看来,tableview 将先前大小的单元格保留在队列中,并且不会自动更新其字体大小以响应用户对首选文本大小的更改。但是我不明白为什么当队列包含普通的非子类实例时 tableview会自动进行此更改。UITableViewCell有什么方法可以在不重新启动应用程序(或不重新创建UITableView实例,从而清空队列)的情况下使其工作?有没有办法以编程方式(和合法地)清除这个队列?

编辑:如果有人对此问题感兴趣,我对此的直接修复是编写一个通用实用程序方法来创建一个新的 tableview,复制原始 tableview 中的所有相关属性(包括注册的单元格类),然后交换旧的换新的。由于这是一个新表,它会生成包含新文本大小的排队单元的全新实例。

4

3 回答 3

1

这现在在 iOS 10 中为您处理。

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

在您的标签上设置adjustsFontForContentSizeCategoryYES/ true,当文本大小首选项发生变化时,它会自动调整大小。

于 2016-07-12T00:15:39.250 回答
0

根据您的描述,您似乎只想在用户将其作为背景后视图返回屏幕时重新加载表格。为了以我认为您想要的方式实现这一点,您需要在您的 tableView 的 init 方法中添加以下内容 - 它会告诉您的 tableView 在应用程序即将进入前台时正确重新加载单元格:

[[NSNotificationCenter defaultCenter] addObserver:self.tableView selector:@selector(reloadData) name:UIApplicationWillEnterForegroundNotification object:nil];

这样,如果用户在进入手机设置后通过打开应用程序返回视图,您的 tableView 应该重新加载并且应该正确反映更改(如果进行了任何更改)。

你可以在这里看到我测试的结果的快速视频:

https://www.dropbox.com/s/pvjuiyofydnxnvd/textsize.mov

编辑:

就像您在之前的评论中所说的那样,您的 nib 实现似乎有问题。唯一的区别是更新标签属性的位置/方式。在自定义单元格中,我创建了一个标签属性和一个字体属性,并在 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) {do stuff here that are common for all cells} 然后您执行特定于每个单元格的事情的原因,以及为什么即使您假设 reloadData 这个代码仍然有效没有“清除队列”,我不相信在阅读 UITableView 文档后它不会。

于 2014-01-19T04:17:30.840 回答
0

我对此的直接修复是编写一个通用实用程序方法,该方法创建一个新的 tableview,从原始 tableview 复制所有相关属性(包括注册的单元格类),然后将新的属性替换为旧的。由于这是一个新表,它会生成包含新文本大小的排队单元的全新实例。

于 2015-09-18T20:21:30.197 回答