Правильний API, який використовується, є UIView systemLayoutSizeFittingSize:
проходження UILayoutFittingCompressedSize
або UILayoutFittingExpandedSize
.
Для звичайного UIView
використання автоматичного розкладу це повинно працювати лише до тих пір, поки ваші обмеження будуть правильними. Якщо ви хочете використовувати його на UITableViewCell
(наприклад, щоб визначити висоту рядка), тоді слід зателефонувати йому до своєї комірки contentView
та схопити висоту.
Подальші міркування існують, якщо у вас є один або кілька UILabel, які є багатолінійними. Для цього не є властивим встановити preferredMaxLayoutWidth
властивість правильно таким чином, щоб мітка містила правильну інформацію intrinsicContentSize
, яка буде використана при systemLayoutSizeFittingSize's
обчисленні.
EDIT: за запитом, додаючи приклад розрахунку висоти для комірки подання таблиці
Використання автоматичного розкладу для обчислення висоти комірки таблиці не надто ефективно, але це, звичайно, зручно, особливо якщо у вас клітина зі складною компонуванням.
Як я вже говорив вище, якщо ви використовуєте багаторядкові 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, що демонструє висотуForRowAtIndexPath:
#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
: