Tamaño dynamic uitableViewCell según UILabel (con espaciado entre párrafos)

Tengo un UITableView que está lleno de texto e imágenes de un archivo JSON. Actualmente, la celda TableView está dimensionando correctamente para las “publicaciones” que no contienen muchos saltos de línea en el texto; sin embargo, no puedo calcular la altura correcta para las “publicaciones” con 4 o 5 saltos de línea.

Código para obtener altura:

-(float)height :(NSMutableAttributedString*)string { NSString *stringToSize = [NSString stringWithFormat:@"%@", string]; CGSize constraint = CGSizeMake(LABEL_WIDTH - (LABEL_MARGIN *2), 2000.f); CGSize size = [stringToSize sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:contraint lineBreakMode:NSLineBreakByWordWrapping]; return size.height; } 

¿Cómo calculo el tamaño correcto al tiempo que se permiten saltos de línea y espacios en blanco?

EDITAR

El rest del método,

Dentro de TableView CellForRow:

 -(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSString *row = [NSString stringWithFormat:@"%i", indexPath.row]; float postTextHeight = [self height:postText]; NSString *height = [NSString stringWithFormat:@"%f", heightOfPostText + 70]; [_cellSizes setObject:height forKey:row]; } 

Y la altura de Table Cell:

 -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { NSString *imageHeightString = [NSString stringWithFormat:@"%@", [_cellSizes objectForKey:indexPath.row]]; float heightOfCell = [imageHeightString floatValue]; if (heightOfCell == 0) { return 217; }; return heightOfCell + 5; } 

es mejor que primero calcule la altura, no incluya la parte del cálculo de la altura en el método:

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 

Mejor calcularlo en método:

 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 

dado que está obteniendo los datos de json, es fácil calcularlo en el método “heightForRowAtIndexPath”.

El siguiente código le dará el ejemplo para calcular la altura del texto, cambie su requisito. Espero que esto te ayude 🙂

 // i am using an array - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. UIFont *labelFont = [UIFont fontWithName:@"Noteworthy-Bold" size:20]; NSDictionary *arialdict = [NSDictionary dictionaryWithObject:labelFont forKey:NSFontAttributeName]; NSMutableAttributedString *message = [[NSMutableAttributedString alloc] initWithString:@"this is just the sample example of how to calculate the dynamic height for tableview cell which is of around 7 to 8 lines. you will need to set the height of this string first, not seems to be calculated in cellForRowAtIndexPath method." attributes:arialdict]; array = [NSMutableArray arrayWithObjects:message, nil]; NSMutableAttributedString *message_1 = [[NSMutableAttributedString alloc] initWithString:@"you will need to set the height of this string first, not seems to be calculated in cellForRowAtIndexPath method." attributes:arialdict]; [array addObject:message_1]; } - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 2; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 2; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *Cell = [self.aTableView dequeueReusableCellWithIdentifier:@"cell"]; if(Cell == nil) { Cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"]; } //dont include the height calculation part hear, becz heights are already set for all the cell [Cell.textLabel sizeToFit]; Cell.textLabel.attributedText = [array objectAtIndex:indexPath.row]; // dont calculate height hear it will be called after "heightForRowAtIndexPath" method Cell.textLabel.numberOfLines = 8; return Cell; } // put ur height calculation method i took some hardcoded values change it :) -(float)height :(NSMutableAttributedString*)string { /* NSString *stringToSize = [NSString stringWithFormat:@"%@", string]; // CGSize constraint = CGSizeMake(LABEL_WIDTH - (LABEL_MARGIN *2), 2000.f); CGSize maxSize = CGSizeMake(280, MAXFLOAT);//set max height //set the constant width, hear MAXFLOAT gives the maximum height CGSize size = [stringToSize sizeWithFont:[UIFont systemFontOfSize:20.0f] constrainedToSize:maxSize lineBreakMode:NSLineBreakByWordWrapping]; return size.height; //finally u get the correct height */ //commenting the above code because "sizeWithFont: constrainedToSize:maxSize: lineBreakMode: " has been deprecated to avoid above code use below NSAttributedString *attributedText = string; CGRect rect = [attributedText boundingRectWithSize:(CGSize){225, MAXFLOAT} options:NSStringDrawingUsesLineFragmentOrigin context:nil];//you need to specify the some width, height will be calculated CGSize requiredSize = rect.size; return requiredSize.height; //finally u return your height } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { //whatever the height u need to calculate calculate hear only CGFloat heightOfcell = [self height:[array objectAtIndex:indexPath.row]]; NSLog(@"%f",heightOfcell); return heightOfcell; } 

Espero que esto te ayude 🙂

Para la versión SWIFT

 class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate { var messageArray:[String] = [] //array to holde the response form son for example override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. messageArray = ["One of the most interesting features of Newsstand is that once an asset downloading has started it will continue even if the application is suspended (that is: not running but still in memory) or it is terminated. Of course during while your app is suspended it will not receive any status update but it will be woken up in the background", "In case that app has been terminated while downloading was in progress, the situation is different. Infact in the event of a finished downloading the app can not be simply woken up and the connection delegate finish download method called, as when an app is terminated its App delegate object doesn't exist anymore. In such case the system will relaunch the app in the background.", " If defined, this key will contain the array of all asset identifiers that caused the launch. From my tests it doesn't seem this check is really required if you reconnect the pending downloading as explained in the next paragraph.", ] } func numberOfSectionsInTableView(tableView: UITableView) -> Int { return 1; } func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return messageArray.count; } func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { var cell:UITableViewCell? = tableView.dequeueReusableCellWithIdentifier("CELL") as? UITableViewCell; if(cell == nil) { cell = UITableViewCell(style:UITableViewCellStyle.Default, reuseIdentifier: "CELL") cell?.selectionStyle = UITableViewCellSelectionStyle.None } cell?.textLabel.font = UIFont.systemFontOfSize(15.0) cell?.textLabel.sizeToFit() cell?.textLabel.text = messageArray[indexPath.row] cell?.textLabel.numberOfLines = 0 return cell!; } func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { var height:CGFloat = self.calculateHeightForString(messageArray[indexPath.row]) return height + 70.0 } func calculateHeightForString(inString:String) -> CGFloat { var messageString = inString var attributes = [UIFont(): UIFont.systemFontOfSize(15.0)] var attrString:NSAttributedString? = NSAttributedString(string: messageString, attributes: attributes) var rect:CGRect = attrString!.boundingRectWithSize(CGSizeMake(300.0,CGFloat.max), options: NSStringDrawingOptions.UsesLineFragmentOrigin, context:nil ) var requredSize:CGRect = rect return requredSize.height //to include button's in your tableview } } 

@Shan tuvo una buena respuesta, pero no funcionó del todo para mí.

Este es el código que utilicé para calcular la altura de la celda

 -(float)height :(NSMutableAttributedString*)string { CGRect rect = [string boundingRectWithSize:(CGSize){table.frame.size.width - 110, MAXFLOAT} options:NSStringDrawingUsesLineFragmentOrigin context:nil]; return rect.size.height; } 

Hago el -110 porque eso dará el mismo espacio en los lados superior e inferior.

Espero que esto ayude.

Implemente este método delegado de vista de tabla:

-tableView: heightForRowAtIndexPath:

https://developer.apple.com/library/ios/documentation/uikit/reference/UITableViewDelegate_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/UITableViewDelegate/tableView:heightForRowAtIndexPath :

Llamarás a tu método para determinar la altura y devolverás ese valor con algo de relleno extra si lo deseas.

El enfoque que recomiendo es establecer el texto de una etiqueta real y obtener la altura requerida llamando a sizeToFit . Para que esto funcione, debe establecer la propiedad numberOfLines la etiqueta en 0 y establecer el ancho máximo deseado.

Al usar esta técnica con vistas de tabla, puede usar el método de celda prototipo que se discute aquí para calcular la altura usando una celda real.