La API correcta para usar es UIView systemLayoutSizeFittingSize:
, pasando cualquiera UILayoutFittingCompressedSize
o UILayoutFittingExpandedSize
.
Para una UIView
distribución automática normal, esto debería funcionar siempre que sus restricciones sean correctas. Si desea usarlo en un UITableViewCell
(para determinar la altura de la fila, por ejemplo), debe llamarlo contra su celda contentView
y tomar la altura.
Existen otras consideraciones si tiene uno o más UILabel en su punto de vista que son multilínea. Para estos es imperitivo que la preferredMaxLayoutWidth
propiedad se establezca correctamente de modo que la etiqueta proporcione una correcta intrinsicContentSize
, que se utilizará en el systemLayoutSizeFittingSize's
cálculo.
EDITAR: por solicitud, agregando un ejemplo de cálculo de altura para una celda de vista de tabla
El uso de la distribución automática para el cálculo de la altura de la celda de la tabla no es súper eficiente, pero sin duda es conveniente, especialmente si tiene una celda que tiene un diseño complejo.
Como dije anteriormente, si está utilizando una línea múltiple UILabel
, es imprescindible sincronizarlo preferredMaxLayoutWidth
con el ancho de la etiqueta. Yo uso una UILabel
subclase personalizada para hacer esto:
@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
Aquí hay una subclase inventada de UITableViewController que demuestra 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
Una celda personalizada simple:
#import "TSTableViewCell.h"
#import "TSLabel.h"
@implementation TSTableViewCell
{
IBOutlet TSLabel* _label;
}
- (void) setText: (NSString *) text
{
_label.text = text;
}
@end
Y, aquí hay una imagen de las restricciones definidas en el Storyboard. Tenga en cuenta que no hay restricciones de alto / ancho en la etiqueta, que se infieren de las etiquetas intrinsicContentSize
: