UITextView Inside UITableViewCell Auto-Layout iOS 6 vs. iOS 7

Estoy construyendo una pantalla de posts como parte de la aplicación que estoy escribiendo. Actualmente, es un UITableView contiene celdas que son mi propia subclass personalizada de UITableViewCell . Estoy usando layout automático con restricciones en la celda definida en Interface Builder. Mis posts imitan, o intentan imitar, la aplicación de postría pnetworkingeterminada. Hay tres componentes principales de cada celda de vista de tabla: un UITextView contiene el cuerpo del post y dos UILabel s adicionales, uno para el nombre del remitente y / o el sello de time, y el otro para los recibos entregados / leídos.

Ahora, usando el layout automático combinado con tableView:heightForRowAtIndexPath: en mi controller de vista, se supone que la vista de text del post en cada celda de vista de tabla crezca de acuerdo con el tamaño del post (uso sizeWithFont:constainedToSize:lineBreakMode en este momento, sé que es en desuso, pero los reemploops no funcionan en iOS 6 y también son escamosas hasta el momento). Esto funciona bien cuando las tags y la vista de text están todas presentes en la interfaz de usuario. Sin embargo, en un subprocess de post individual, removeFromSuperview label de lectura / entrega utilizando removeFromSuperview para todas las celdas de posts, pero el post final (si el post final es enviado por usted). Esto no causa efectos adversos en iOS 7, pero en iOS 6, cualquier celda que tenga una label eliminada hace que la vista de text tenga una altura de 0.0 (confirmada por las salidas de debugging). Volver a agregar la label y las restricciones de layout automático apropiadas parece solucionarlo, pero en cualquier celda donde se elimine esa label, incluso si calculo una altura positiva para la vista de text en tableView:heightForRowAtIndexPath: el alto de vista de text es cero, y la label restante termina desplazada hacia arriba para "aparecer" para sobrescribir la vista de text.

Supongo que quitar una vista de su supervisor es el culpable principal aquí, pero no entiendo por qué esto ocurriría solo en iOS 6 en lugar de los 6 y 7.

Ahora el codigo Aquí está mi cellForRowAtIndexPath: y heightForRowAtIndexPath: methods

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString * sentMessageCellIdentifier = @"sentMessageCell"; static NSString * receivedMessageCellIdentifier = @"receivedMessageCell"; MessageCell * cell; Message * messageObject = [associatedThread.messages objectAtIndex:indexPath.row]; GroupMember * selfMm = [associatedThread.parentGroup groupMemberForUser:[ApplicationInstance getInstance].currentUser]; if ([messageObject.sender isEqualToGroupMember:selfMm]) { // Sent cell = (MessageCell *) [tableView dequeueReusableCellWithIdentifier:sentMessageCellIdentifier]; cell.sentTimeLabel.text = [UtilityFunctions messageFriendlyFormattedDateTimeForDate:messageObject.messageTime]; if ([messageObject isEqualToMessage:[associatedThread.messages lastObject]]) { cell.delivenetworkingReadByLabel.text = @"Sent"; } else { cell.delivenetworkingReadByLabel.text = nil; } } else { // Received cell = (MessageCell *) [tableView dequeueReusableCellWithIdentifier:receivedMessageCellIdentifier]; [cell setSenderAndDateTimeForSender:messageObject.sender date:messageObject.messageTime]; } // Read by label NSString * readByText = nil; if (associatedThread.parentGroupMember == nil) { // Group thread if (messageObject.readBy.count == 0) { if (![messageObject.sender isEqualToGroupMember:selfMm]) { readByText = @"Read by: only you"; } } else { NSInteger readByCount = messageObject.readBy.count; NSInteger toSubtract = [messageObject.sender isEqualToGroupMember:selfMm] ? 1 : 2; if (readByCount == associatedThread.members.count - toSubtract) { // If everyone read it (minus you and the sender) readByText = @"Read by everyone"; } else { GroupMember * randRbm = [messageObject.readBy firstObject]; if (messageObject.readBy.count == 1) { cell.delivenetworkingReadByLabel.text = [NSString stringWithFormat:@"Read by: %@", randRbm.user.displayName]; } else if (messageObject.readBy.count > 1) { cell.delivenetworkingReadByLabel.text = [NSString stringWithFormat:@"Read by: %@ + %d", randRbm.user.displayName, messageObject.readBy.count - 1]; } cell.delivenetworkingReadByLabel.userInteractionEnabled = YES; [cell.delivenetworkingReadByLabel addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapReadByLabel:)]]; } } } else { // One-on-one individual thread if ([messageObject isEqualToMessage:[associatedThread.messages lastObject]] && [messageObject.sender isEqualToGroupMember:selfMm]) { if (cell.delivenetworkingReadByLabel.superview == nil) { [cell.contentView addSubview:cell.delivenetworkingReadByLabel]; // Auto-layout bindings NSArray * constaints = @[[NSLayoutConstraint constraintWithItem:cell.delivenetworkingReadByLabel attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:cell.sentTimeLabel attribute:NSLayoutAttributeBottom multiplier:1.0 constant:1.0], [NSLayoutConstraint constraintWithItem:cell.delivenetworkingReadByLabel attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:cell.contentView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:20.0], [NSLayoutConstraint constraintWithItem:cell.delivenetworkingReadByLabel attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:cell.contentView attribute:NSLayoutAttributeRight multiplier:1.0 constant:-20.0], [NSLayoutConstraint constraintWithItem:cell.delivenetworkingReadByLabel attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:cell.contentView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-5.0] ]; [cell addConstraints:constaints]; } if (messageObject.readBy.count == 1) { readByText = @"Read"; } } else { [cell.delivenetworkingReadByLabel removeFromSuperview]; } } if (readByText != nil) { cell.delivenetworkingReadByLabel.text = readByText; } debugLog(@"%@", [messageObject isEqualToMessage:[associatedThread.messages lastObject]] ? @"YES" : @"NO"); debugLog(@"x,y [%f, %f] | w,h [%f, %f] - message view", cell.messageView.frame.origin.x, cell.messageView.frame.origin.y, cell.messageView.frame.size.width, cell.messageView.frame.size.height); debugLog(@"x,y [%f, %f] | w,h [%f, %f] - sent time label", cell.sentTimeLabel.frame.origin.x, cell.sentTimeLabel.frame.origin.y, cell.sentTimeLabel.frame.size.width, cell.sentTimeLabel.frame.size.height); debugLog(@"x,y [%f, %f] | w,h [%f, %f] - sender time label", cell.senderAndDateTimeLabel.frame.origin.x, cell.senderAndDateTimeLabel.frame.origin.y, cell.senderAndDateTimeLabel.frame.size.width, cell.senderAndDateTimeLabel.frame.size.height); debugLog(@"x,y [%f, %f] | w,h [%f, %f] - delivenetworking label", cell.delivenetworkingReadByLabel.frame.origin.x, cell.delivenetworkingReadByLabel.frame.origin.y, cell.delivenetworkingReadByLabel.frame.size.width, cell.delivenetworkingReadByLabel.frame.size.height); // Message body [UtilityFunctions setZeroInsetsForTextView:cell.messageView]; cell.messageView.text = messageObject.messageBody; cell.messageView.scrollEnabled = YES; cell.messageView.scrollEnabled = NO; return cell; } - (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *) indexPath { CGFloat totalHeight = 0.0; Message * m = [associatedThread.messages objectAtIndex:indexPath.row]; // Top and bottom padding totalHeight += 5.0 + 5.0; // Height + padding between labels (and text view) totalHeight += 14.0 + 14.0 + 1.0 + 1.0; // height + height + padding + padding // Modify UI slightly if incoming message and one-on-one thread: if (associatedThread.parentGroupMember != nil) { totalHeight -= (14.0 + 1.0); if ([m isEqualToMessage:[associatedThread.messages lastObject]]) { if ([m.sender isEqualToGroupMember:[associatedThread.parentGroup groupMemberForUser:[ApplicationInstance getInstance].currentUser]]) { totalHeight += (14.0 + 1.0); } } } NSString * bodyText = m.messageBody; CGSize constraint = CGSizeMake(MESSAGE_TEXT_WIDTH_MAX, CGFLOAT_MAX); CGSize sizeWithFont = [bodyText sizeWithFont:[UIFont systemFontOfSize:16.0] constrainedToSize:constraint lineBreakMode:NSLineBreakByWordWrapping]; totalHeight += sizeWithFont.height + 1.0; // 1.0 because iOS hates me if ([m isEqualToMessage:[associatedThread.messages lastObject]]) { debugLog(@"YES"); } else { debugLog(@"NO"); } debugLog(@"height: %f", totalHeight); return totalHeight; } 

Aquí están las restricciones que establecí en Interface Builder. Tenga en count el ancho estático de la vista de text del post:

Restricciones de diseño automático

Y así es como se ve en iOS 6 (notas: los colors son para mi propia ayuda visual, obviamente no se mantendrá así, y el simulador / dispositivo produce los mismos resultados):

iOS 6

Aquí está el comportamiento esperado en iOS 7, como deseo que se comporte:

iOS7

Es importante tener en count que la altura de la celda de vista de tabla real parece correcta, pero la vista de text no se está ajustando en consecuencia, a pesar de que he intentado ajustar mi código en ambos methods anteriores e intenté diferentes técnicas en vano . Estoy bastante seguro de que necesito usar removeFromSuperview ya que es la única manera de utilizar el layout automático y acomodar lo que estoy tratando de hacer. La label entregada / leída se elimina bajo las siguientes condiciones:

  • Hay dos personas en el hilo de posts
  • El post es el último post en el hilo.
  • Ese último post fue enviado por usted

Sé que esta es una pregunta terriblemente específica, pero si alguien tiene ideas sobre por qué ocurre esto, estaría agradecido. Tenga en count que la vista de text no es editable, aunque es seleccionable.

Como siempre, gracias.

Edit: También ocasionalmente obtendré iOS 6 para lanzar Assertion failure in -[UITableViewCell layoutSublayersOfLayer:] aunque mi subclass personalizada no implemente esa function. Ya se quejó de las limitaciones antes, pero esa es una broma para reproducir ese error.

UILabel esto cediendo y manteniendo a UILabel s en la celda en todo momento. Simplemente seré inteligente sobre cómo organizar la date y leer los bys. Dejaré esto por si alguien tiene un problema similar en el futuro.