Правильный API для использования UIView systemLayoutSizeFittingSize:
, передавая либо UILayoutFittingCompressedSize
или UILayoutFittingExpandedSize
.
Для обычного UIView
использования autolayout это должно работать, пока ваши ограничения верны. Если вы хотите использовать его в UITableViewCell
(например, для определения высоты строки), вы должны вызвать его напротив своей ячейки contentView
и взять высоту.
Дополнительные соображения существуют, если у вас есть один или несколько UILabel по вашему мнению, которые являются многострочными. Для них не обязательно, чтобы preferredMaxLayoutWidth
свойство было установлено правильно, чтобы метка предоставляла правильное значение intrinsicContentSize
, которое будет использоваться при systemLayoutSizeFittingSize's
расчете.
РЕДАКТИРОВАТЬ: по запросу, добавив пример расчета высоты для ячейки табличного представления
Использование autolayout для расчета высоты ячейки таблицы не очень эффективно, но, безусловно, удобно, особенно если у вас есть ячейка со сложным макетом.
Как я уже говорил выше, если вы используете мультилинию UILabel
, обязательно синхронизируйте ее preferredMaxLayoutWidth
с шириной метки. Я использую пользовательский UILabel
подкласс для этого:
@implementation TSLabel
- (void) layoutSubviews
{
[super layoutSubviews];
if ( self.numberOfLines == 0 )
{
if ( self.preferredMaxLayoutWidth != self.frame.size.width )
{
self.preferredMaxLayoutWidth = self.frame.size.width;
[self setNeedsUpdateConstraints];
}
}
}
- (CGSize) intrinsicContentSize
{
CGSize s = [super intrinsicContentSize];
if ( self.numberOfLines == 0 )
{
// found out that sometimes intrinsicContentSize is 1pt too short!
s.height += 1;
}
return s;
}
@end
Вот надуманный подкласс UITableViewController, демонстрирующий heightForRowAtIndexPath:
#import "TSTableViewController.h"
#import "TSTableViewCell.h"
@implementation TSTableViewController
- (NSString*) cellText
{
return @"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";
}
#pragma mark - Table view data source
- (NSInteger) numberOfSectionsInTableView: (UITableView *) tableView
{
return 1;
}
- (NSInteger) tableView: (UITableView *)tableView numberOfRowsInSection: (NSInteger) section
{
return 1;
}
- (CGFloat) tableView: (UITableView *) tableView heightForRowAtIndexPath: (NSIndexPath *) indexPath
{
static TSTableViewCell *sizingCell;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sizingCell = (TSTableViewCell*)[tableView dequeueReusableCellWithIdentifier: @"TSTableViewCell"];
});
// configure the cell
sizingCell.text = self.cellText;
// force layout
[sizingCell setNeedsLayout];
[sizingCell layoutIfNeeded];
// get the fitting size
CGSize s = [sizingCell.contentView systemLayoutSizeFittingSize: UILayoutFittingCompressedSize];
NSLog( @"fittingSize: %@", NSStringFromCGSize( s ));
return s.height;
}
- (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath
{
TSTableViewCell *cell = (TSTableViewCell*)[tableView dequeueReusableCellWithIdentifier: @"TSTableViewCell" ];
cell.text = self.cellText;
return cell;
}
@end
Простая пользовательская ячейка:
#import "TSTableViewCell.h"
#import "TSLabel.h"
@implementation TSTableViewCell
{
IBOutlet TSLabel* _label;
}
- (void) setText: (NSString *) text
{
_label.text = text;
}
@end
И вот картина ограничений, определенных в раскадровке. Обратите внимание, что на метке нет ограничений по высоте / ширине - они выведены из меток intrinsicContentSize
: