iOS8 大小为 类 的 UIView.systemLayoutSizeFittingSize 的值不正确

iOS8 incorrrect value of UIView.systemLayoutSizeFittingSize with Size Classes

Size Classes 在 iOS 8 上运行时,我遇到了方法 UIView.systemLayoutSizeFittingSize 的奇怪问题。 例如,我使用 Paul 的自动高度单元教程项目。也可以找到用于演示目的的带有我的修改的项目 here

所以 iOS 7 看起来不错。


但是在 iOS 8 方法上 return 值要小得多,然后细胞开始分裂。


Size Classes 关闭时,这个问题就消失了。我不知道如何解决这个问题,目前我知道的唯一解决方案是 Size Classes.

代码

ViewController.m(108行)

#import "ViewController.h"
#import "CustomTableViewCell.h"

@interface ViewController () <UITableViewDataSource, UITableViewDelegate> {
    
    NSMutableArray *_fontArray;
    NSMutableArray *_quoteArray;
    
}

@property (weak, nonatomic) IBOutlet UITableView *tableView;
@property (strong, nonatomic) CustomTableViewCell *customCell;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    self.tableView.delegate = self;
    self.tableView.dataSource = self;
    
//    self.navigationItem.rightBarButtonItem = self.editButtonItem;
    
    _fontArray = [[UIFont familyNames] mutableCopy];
    for(int i = 0; i < 100; i++) {
        [_fontArray addObjectsFromArray:[UIFont familyNames]];
    }
    NSLog(@"Size: %d", [_fontArray count]);
    
    _quoteArray = [@[@"For the past 33 years, I have looked in the mirror every morning and asked myself: 'If today were the last day of my life, would I want to do what I am about to do today?' And whenever the answer has been 'No' for too many days in a row, I know I need to change something. -Steve Jobs",
                     @"Be a yardstick of quality. Some people aren't used to an environment where excellence is expected. - Steve Jobs",
                     @"Innovation distinguishes between a leader and a follower. -Steve Jobs"] mutableCopy];
    
 
    // Use iOS 8 new auto sizing feature for heights (don't need to calculate yourself)
//    _tableView.rowHeight = UITableViewAutomaticDimension;
    
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    
    return [_fontArray count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    CustomTableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"CustomCell"];
    
    cell.fontNameLabel.text = _fontArray[indexPath.row];
    
    int quoteIndex = indexPath.row % [_quoteArray count];
    cell.quoteLabel.text = _quoteArray[quoteIndex];
    cell.quoteLabel2.text = _quoteArray[quoteIndex];
    NSString *fontName = _fontArray[indexPath.row];
    cell.quoteLabel.font = [UIFont fontWithName:fontName size:17];
    cell.quoteLabel2.font = [UIFont fontWithName:fontName size:17];
    return cell;
    
}

// NOTE: in iOS 8 you can use the automatic height calculations from AutoLayout,
//  and you can avoid writing this height method. Just comment it out, and uncomment
//  the line in viewDidLoad for
//  _tableView.rowHeight = UITableViewAutomaticDimension;
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    // Calculate a height based on a cell
    if(!self.customCell) {
        self.customCell = [self.tableView dequeueReusableCellWithIdentifier:@"CustomCell"];
    }
    
    // Configure the cell
    self.customCell.fontNameLabel.text = _fontArray[indexPath.row];
    
    int quoteIndex = indexPath.row % [_quoteArray count];
    self.customCell.quoteLabel.text = _quoteArray[quoteIndex];
    self.customCell.quoteLabel2.text = _quoteArray[quoteIndex];
    NSString *fontName = _fontArray[indexPath.row];
    self.customCell.quoteLabel.font = [UIFont fontWithName:fontName size:17];
    self.customCell.quoteLabel2.font = [UIFont fontWithName:fontName size:17];

    
    // Layout the cell
    
    [self.customCell layoutIfNeeded];
    
    // Get the height for the cell

    CGFloat height = [self.customCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
    
    // Padding of 1 point (cell separator)
    CGFloat separatorHeight = 1;
    NSLog(@"%f",height);
    
    return height + separatorHeight;
}

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    return 140;
    
}

@end

CustomTableViewCell.h(10 行)

#import <UIKit/UIKit.h>

@interface CustomTableViewCell : UITableViewCell

@property (weak, nonatomic) IBOutlet UILabel *quoteLabel;
@property (weak, nonatomic) IBOutlet UILabel *fontNameLabel;
@property (strong, nonatomic) IBOutlet UILabel *quoteLabel2;

@end

CustomTableViewCell.m(39 行)

#import "CustomTableViewCell.h"

@implementation CustomTableViewCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        // Initialization code
    }
    return self;
}

- (void)awakeFromNib
{
    // Initialization code
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    [super setSelected:selected animated:animated];

    // Configure the view for the selected state
}

// CODE FIX layouts by setting the maxPreferredWidth on any UILabel that can be
//  multiline – you may have to do similar settings to other UI elements
//  This logic fixes the layout for any UILabels that don't go up to the margins, they
//  might be offset by a constraint that isn't the standard.

- (void)layoutSubviews {
    [super layoutSubviews];
    [self.contentView layoutIfNeeded];
    self.fontNameLabel.preferredMaxLayoutWidth = self.fontNameLabel.frame.size.width;
    self.quoteLabel.preferredMaxLayoutWidth = self.quoteLabel.frame.size.width;
    self.quoteLabel2.preferredMaxLayoutWidth = self.quoteLabel2.frame.size.width;
}

@end

您的问题可能是因为当您使用使用 dequeueReusableCellWithIdentifier 创建的原型单元格时,返回的单元格没有大小 class,因为它不是视图层次结构的一部分,因此没有traitCollection与之关联。

我通过临时将单元格添加到 table 视图、调整大小然后将其删除来解决这个问题。添加时,customCell 获取控制器和布局的大小 class,然后使用任何大小 class 相关的字体、约束等...实际单元格没有相同的问题,因为它们的大小为 class 作为 UITableView 的一部分。

因此请尝试按如下方式更改您的身高计算方式:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    // Calculate a height based on a cell
    if(!self.customCell) {
        self.customCell = [self.tableView dequeueReusableCellWithIdentifier:@"CustomCell"];
    }

    // ***
    // *** Add custom cell to the table view so it obtains a size class
    // *** for layout. Also mark it as needing layout.
    // ***
    [self.tableView addSubview:customCell];
    [customCell setNeedsLayout];

    // Configure the cell
    self.customCell.fontNameLabel.text = _fontArray[indexPath.row];

    int quoteIndex = indexPath.row % [_quoteArray count];
    self.customCell.quoteLabel.text = _quoteArray[quoteIndex];
    self.customCell.quoteLabel2.text = _quoteArray[quoteIndex];
    NSString *fontName = _fontArray[indexPath.row];
    self.customCell.quoteLabel.font = [UIFont fontWithName:fontName size:17];
    self.customCell.quoteLabel2.font = [UIFont fontWithName:fontName size:17];


    // Layout the cell

    [self.customCell layoutIfNeeded];

    // Get the height for the cell

    CGFloat height = [self.customCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;

    // Padding of 1 point (cell separator)
    CGFloat separatorHeight = 1;
    NSLog(@"%f",height);

    // ***
    // *** Remove cell from the table view
    // ***
    [customCell removeFromSuperview];

    return height + separatorHeight;
}