Правильный 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:
