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;
}
当 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;
}