나는이 UITableView
사용자 정의로 UITableViewCell
자동 레이아웃을 사용하여 스토리 보드에 정의. 셀에는 여러 줄이 있습니다 UILabels
.
에서 UITableView
셀 높이를 올바르게 계산 하는 것처럼 보이지만 처음 몇 셀의 경우 해당 높이가 레이블간에 제대로 나뉘 지 않습니다. 조금 스크롤하면 모든 것이 예상대로 작동합니다 (처음에 올바르지 않은 셀도 포함).
- (void)viewDidLoad {
[super viewDidLoad]
// ...
self.tableView.rowHeight = UITableViewAutomaticDimension;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"TestCell"];
// ...
// Set label.text for variable length string.
return cell;
}
내가 놓칠 수있는 것이 있는데, 이로 인해 자동 레이아웃이 처음 몇 번 작업을 수행 할 수 없습니까?
이 동작을 보여주는 샘플 프로젝트 를 만들었습니다 .
답변
이것이 명확하게 문서화되었는지 여부는 모르지만 [cell layoutIfNeeded]
셀을 반환하기 전에 추가하면 문제가 해결됩니다.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"TestCell"];
NSUInteger n1 = firstLabelWordCount[indexPath.row];
NSUInteger n2 = secondLabelWordCount[indexPath.row];
[cell setNumberOfWordsForFirstLabel:n1 secondLabel:n2];
[cell layoutIfNeeded]; // <- added
return cell;
}
답변
이것은 다른 유사한 솔루션이 그렇지 않은 경우 저에게 효과적이었습니다.
override func didMoveToSuperview() {
super.didMoveToSuperview()
layoutIfNeeded()
}
AutoLayout과 UITableViewAutomaticDimension을 사용하는 방법에 매우 익숙하기 때문에 실제 버그처럼 보이지만 가끔이 문제가 발생합니다. 마침내 해결 방법으로 작동하는 것을 발견하게되어 기쁩니다.
답변
처음에보기 밖으로 스크롤 된 셀에는 추가 기능 [cell layoutIfNeeded]
이 cellForRowAtIndexPath
작동하지 않습니다.
또한 [cell setNeedsLayout]
.
특정 셀의 크기를 올바르게 조정하려면 여전히 특정 셀을보기로 스크롤해야합니다.
대부분의 개발자는이 성가신 경우를 제외하고는 Dynamic Type, AutoLayout 및 Self-Sizing Cell이 제대로 작동하므로 매우 실망 스럽습니다. 이 버그는 모든 “더 큰”테이블 뷰 컨트롤러에 영향을줍니다.
답변
내 프로젝트 중 하나에서 같은 경험을했습니다.
왜 발생합니까?
일부 장치에 대해 약간의 너비가있는 스토리 보드에서 디자인 된 셀. 예 : 400px. 예를 들어 라벨의 너비가 동일합니다. 스토리 보드에서로드 할 때 너비는 400px입니다.
여기에 문제가 있습니다.
tableView:heightForRowAtIndexPath:
셀 레이아웃 전에 호출됩니다.
그래서 레이블과 셀의 높이를 400px 너비로 계산했습니다. 하지만 화면이있는 기기 (예 : 320px)에서 실행합니다. 그리고이 자동 계산 된 높이는 올바르지 않습니다. 라벨을 수동으로
설정 layoutSubviews
한 tableView:heightForRowAtIndexPath:
후에도 셀이 발생 하기 때문에 도움이되지 않습니다.preferredMaxLayoutWidth
layoutSubviews
내 솔루션 :
1) 하위 클래스 UITableView
및 재정의 dequeueReusableCellWithIdentifier:forIndexPath:
. 셀 너비를 테이블 너비와 동일하게 설정하고 셀 레이아웃을 적용합니다.
- (UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [super dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
CGRect cellFrame = cell.frame;
cellFrame.size.width = self.frame.size.width;
cell.frame = cellFrame;
[cell layoutIfNeeded];
return cell;
}
2) 하위 클래스 UITableViewCell
. preferredMaxLayoutWidth
에서 레이블을 수동으로 설정 합니다 layoutSubviews
. 또한 contentView
셀 프레임 변경 후 자동으로 레이아웃되지 않기 때문에 수동 레이아웃이 필요합니다 (이유는 모르겠지만 그렇습니다)
- (void)layoutSubviews {
[super layoutSubviews];
[self.contentView layoutIfNeeded];
self.yourLongTextLabel.preferredMaxLayoutWidth = self.yourLongTextLabel.width;
}
답변
비슷한 문제가 있습니다. 첫 번째로드에서 행 높이가 계산되지 않았지만 스크롤하거나 다른 화면으로 이동하면이 화면으로 돌아와 행이 계산됩니다. 첫 번째로드에서 내 항목은 인터넷에서로드되고 두 번째로드에서는 내 항목이 Core Data에서 먼저로드되고 인터넷에서 다시로드되며 인터넷에서 다시로드 할 때 행 높이가 계산되는 것을 확인했습니다. 그래서 segue 애니메이션 중에 tableView.reloadData ()가 호출되면 (푸시 및 현재 segue와 동일한 문제) 행 높이가 계산되지 않는다는 것을 알았습니다. 그래서 뷰 초기화에서 tableview를 숨기고 사용자에게 추악한 영향을 미치지 않도록 활동 로더를 넣고 300ms 후에 tableView.reloadData를 호출하면 문제가 해결됩니다. UIKit 버그라고 생각하지만이 해결 방법이 트릭을 만듭니다.
항목로드 완료 핸들러에 논문 줄 (Swift 3.0)을 넣었습니다.
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(300), execute: {
self.tableView.isHidden = false
self.loader.stopAnimating()
self.tableView.reloadData()
})
이것은 왜 어떤 사람들에게는 layoutSubviews에 reloadData를 넣어 문제를 해결하는지 설명합니다.
답변
위의 솔루션 중 어느 것도 저에게 효과가 없었습니다. 효과가 있었던 것은 마법의 레시피입니다. 다음 순서로 호출하십시오.
tableView.reloadData()
tableView.layoutIfNeeded()
tableView.beginUpdates()
tableView.endUpdates()
내 tableView 데이터는 웹 서비스에서 채워지며 연결의 콜백에서 위의 줄을 작성합니다.
답변
제 경우에는 셀이 처음 표시 될 때 UILabel의 마지막 줄이 잘 렸습니다. 그것은 꽤 무작위로 발생했으며 올바르게 크기를 조정하는 유일한 방법은 뷰에서 셀을 스크롤하고 다시 가져 오는 것입니다. 지금까지 표시된 모든 가능한 솔루션 (layoutIfNeeded..reloadData)을 시도했지만 아무것도 효과가 없었습니다. 트릭은 “Autoshrink” 를 Minimuum Font Scale (저는 0.5) 로 설정하는 것이 었습니다 . 시도 해봐