[英]UITextView Inside UITableViewCell Auto-Layout iOS 6 vs. iOS 7
我正在構建一個消息傳遞屏幕,作為我正在編寫的應用程序的一部分。 目前,它是一個UITableView
包含我自己的UITableViewCell
自定義子類的單元格。 我正在使用自動布局,在Interface Builder中定義的單元格上有約束。 我的消息傳遞模仿或試圖模仿默認消息傳遞應用程序。 每個表格視圖單元格有三個主要組件:包含郵件正文的UITextView
和另外兩個UILabel
,一個用於發件人的名稱和/或時間戳,另一個用於發送/讀取收據。
現在,在我的視圖控制器上使用自動布局結合tableView:heightForRowAtIndexPath:
每個表視圖單元格中的消息文本視圖應該根據消息的大小而增長(我使用sizeWithFont:constainedToSize:lineBreakMode
目前 - 我知道它是已棄用,但替換在iOS 6上不起作用,並且還具有不穩定性。 當UI上的標簽和文本視圖都出現時,這樣可以正常工作。 但是,在單個消息線程中,我使用removeFromSuperview
刪除所有消息單元格的傳遞/讀取標簽,但是最終消息(如果所述最終消息是由您發送的)。 這不會對iOS 7造成不利影響,但在iOS 6上,任何刪除了標簽的單元格都會導致文本視圖的高度為0.0
(由調試輸出確認)。 以編程方式重新添加標簽和適當的自動布局約束似乎解決了它,但在刪除該標簽的任何單元格中,即使我在tableView:heightForRowAtIndexPath:
計算文本視圖的正高度,文本視圖高度為零,並且剩余的標簽最終向上移動到“出現”以覆蓋文本視圖。
我想從其超級視圖中刪除一個視圖是這里的主要罪魁禍首,但我不明白為什么這只會在iOS 6而不是6和7上發生。
現在,代碼。 這是我的cellForRowAtIndexPath:
和heightForRowAtIndexPath:
方法
- (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.deliveredReadByLabel.text = @"Sent";
} else {
cell.deliveredReadByLabel.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.deliveredReadByLabel.text = [NSString stringWithFormat:@"Read by: %@", randRbm.user.displayName];
} else if (messageObject.readBy.count > 1) {
cell.deliveredReadByLabel.text = [NSString stringWithFormat:@"Read by: %@ + %d", randRbm.user.displayName, messageObject.readBy.count - 1];
}
cell.deliveredReadByLabel.userInteractionEnabled = YES;
[cell.deliveredReadByLabel 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.deliveredReadByLabel.superview == nil) {
[cell.contentView addSubview:cell.deliveredReadByLabel];
// Auto-layout bindings
NSArray * constaints = @[[NSLayoutConstraint constraintWithItem:cell.deliveredReadByLabel
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:cell.sentTimeLabel
attribute:NSLayoutAttributeBottom
multiplier:1.0
constant:1.0],
[NSLayoutConstraint constraintWithItem:cell.deliveredReadByLabel
attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationEqual
toItem:cell.contentView
attribute:NSLayoutAttributeLeft
multiplier:1.0
constant:20.0],
[NSLayoutConstraint constraintWithItem:cell.deliveredReadByLabel
attribute:NSLayoutAttributeRight
relatedBy:NSLayoutRelationEqual
toItem:cell.contentView
attribute:NSLayoutAttributeRight
multiplier:1.0
constant:-20.0],
[NSLayoutConstraint constraintWithItem:cell.deliveredReadByLabel
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.deliveredReadByLabel removeFromSuperview];
}
}
if (readByText != nil) {
cell.deliveredReadByLabel.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] - delivered label", cell.deliveredReadByLabel.frame.origin.x, cell.deliveredReadByLabel.frame.origin.y, cell.deliveredReadByLabel.frame.size.width, cell.deliveredReadByLabel.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;
}
以下是我在Interface Builder中設置的約束。 請注意消息文本視圖的靜態寬度:
以下是它在iOS 6中的外觀(注意:顏色是我自己的視覺輔助,它顯然不會保持這種狀態,模擬器/設備產生相同的結果):
這是iOS 7中的預期行為,因為我希望它表現如下:
重要的是要注意實際表格視圖單元格本身的高度看起來是正確的,但文本視圖沒有相應調整,盡管我能夠嘗試在上述兩種方法中調整我的代碼並嘗試不同的技術無濟於事。 我很確定我需要使用removeFromSuperview
因為這是使用自動布局和適應我想要做的事情的唯一方法。 在以下條件下刪除已發送/已讀取的標簽:
我知道這是一個非常具體的問題,但如果有人知道為什么會發生這種情況,我將不勝感激。 請注意,文本視圖不可編輯,但可以選擇。
一如既往,謝謝。
編輯:我偶爾會讓iOS 6 Assertion failure in -[UITableViewCell layoutSublayersOfLayer:]
拋出Assertion failure in -[UITableViewCell layoutSublayersOfLayer:]
即使我的自定義子類沒有實現該功能。 它之前已經抱怨約束,但這是一個重現這個錯誤的廢話。
我通過放棄來解決這個問題,並且一直將UILabel
放在牢房上。 我會巧妙地知道如何安排約會和閱讀。 我會留下這個以防萬一將來有類似的問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.