L'API correcte à utiliser est UIView systemLayoutSizeFittingSize:
en passant soit UILayoutFittingCompressedSize
o UILayoutFittingExpandedSize
.
Pour un UIView
en utilisant autolayout, cela devrait fonctionner tant que vos contraintes sont correctes. Si vous voulez l'utiliser sur un UITableViewCell
(pour déterminer la hauteur de la ligne, par exemple), vous devez l'appeler dans votre cellule. contentView
et saisir la hauteur.
D'autres considérations existent si vous avez un ou plusieurs UILabel dans votre vue qui sont multi-lignes. Dans ce cas, il est impératif que l'élément preferredMaxLayoutWidth
soit correctement définie de manière à ce que l'étiquette fournisse un code d'accès correct. intrinsicContentSize
qui sera utilisé dans systemLayoutSizeFittingSize's
calcul.
EDIT : à la demande, ajout d'un exemple de calcul de la hauteur d'une cellule d'un tableau.
L'utilisation de la mise en page automatique pour le calcul de la hauteur des cellules du tableau n'est pas très efficace, mais elle est très pratique, surtout si la cellule a une disposition complexe.
Comme je l'ai dit plus haut, si vous utilisez un fichier multiligne UILabel
il est impératif de synchroniser les preferredMaxLayoutWidth
à la largeur de l'étiquette. J'utilise un UILabel
pour ce faire :
@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
Voici une sous-classe artificielle de UITableViewController démontrant 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
Une simple cellule personnalisée :
#import "TSTableViewCell.h"
#import "TSLabel.h"
@implementation TSTableViewCell
{
IBOutlet TSLabel* _label;
}
- (void) setText: (NSString *) text
{
_label.text = text;
}
@end
Et, voici une image des contraintes définies dans le Storyboard. Notez qu'il n'y a pas de contraintes de hauteur et de largeur sur l'étiquette - ces contraintes sont déduites de l'attribut intrinsicContentSize
: