NSLayoutConstraint“UIView-Encapsulated-Layout-Height”란 무엇이며 어떻게 깨끗하게 다시 계산해야합니까? [self setNeedsUpdateConstraints]; } 내가

UITableViewiOS 8 에서 실행 중이며 스토리 보드의 제약 조건에서 자동 셀 높이를 사용하고 있습니다.

내 셀 중 하나에 하나가 포함되어 있으며 UITextView사용자 입력을 기반으로 수축 및 확장해야합니다. 텍스트를 축소 / 확장하려면 탭하십시오.

텍스트 뷰에 런타임 제약 조건을 추가하고 사용자 이벤트에 대한 응답으로 제약 조건의 상수를 변경 하여이 작업을 수행합니다.

-(void)collapse:(BOOL)collapse; {

    _collapsed = collapse;

    if(collapse)
        [_collapsedtextHeightConstraint setConstant: kCollapsedHeight]; // 70.0
    else
        [_collapsedtextHeightConstraint setConstant: [self idealCellHeightToShowFullText]];

    [self setNeedsUpdateConstraints];

}

내가 할 때마다 tableView업데이트로 포장 하고 전화 [tableView setNeedsUpdateConstraints]:

[tableView beginUpdates];

[_briefCell collapse:!_showFullBriefText];

[tableView setNeedsUpdateConstraints];
// I have also tried 
// [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationTop];
// with exactly the same results.

[tableView endUpdates];

이 작업을 수행하면 셀이 확장되고 애니메이션이 적용되지만 제약 조건 경고가 표시됩니다.

2014-07-31 13:29:51.792 OneFlatEarth[5505:730175] Unable to simultaneously satisfy constraints.

Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)

(

    "<NSLayoutConstraint:0x7f94dced2b60 V:[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...'(388)]>",

    "<NSLayoutConstraint:0x7f94dced2260 V:[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...']-(15)-|   (Names: '|':UITableViewCellContentView:0x7f94de5773a0 )>",

    "<NSLayoutConstraint:0x7f94dced2350 V:|-(6)-[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...']   (Names: '|':UITableViewCellContentView:0x7f94de5773a0 )>",

    "<NSLayoutConstraint:0x7f94dced6480 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7f94de5773a0(91)]>"
 )

Will attempt to recover by breaking constraint

<NSLayoutConstraint:0x7f94dced2b60 V:[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...'(388)]>

388은 내 계산 높이이며, 다른 제약 조건 UITextView은 Xcode / IB의 광산입니다.

마지막 것은 나를 귀찮게합니다- UIView-Encapsulated-Layout-Height셀이 처음 렌더링 될 때 계산 된 셀 높이 라고 생각합니다 -( UITextView높이를> = 70.0으로 설정) 그러나이 파생 제약 조건이 업데이트 된 사용자 cnstraint.

더 나쁜 것은 레이아웃 코드가 높이 제한을 위반하려고한다고하지만 셀 높이를 다시 계산하지 않고 원하는대로 모든 것을 그립니다.

그렇다면 NSLayoutConstraint UIView-Encapsulated-Layout-Height(자동 셀 크기 조정을 위해 계산 된 높이라고 생각합니다) 무엇이고 깨끗하게 다시 계산하도록하려면 어떻게해야합니까?



답변

우선 순위 _collapsedtextHeightConstraint를 999 로 낮추십시오 . 시스템 제공 UIView-Encapsulated-Layout-Height제한 조건이 항상 우선합니다.

반환 내용을 기반으로합니다 -tableView:heightForRowAtIndexPath:. 올바른 값과 자신의 제약 조건을 반환해야하며 생성 된 제약 조건은 동일해야합니다. 축소 / 확장 애니메이션이 비행하는 동안 충돌을 방지하기 위해 자신의 제약 조건에 대한 우선 순위가 낮을 필요가 있습니다.


답변

UILabel 객체가 몇 줄있는 행 셀이있는 테이블 뷰와 비슷한 시나리오가 있습니다. iOS 8과 자동 레이아웃을 사용하고 있습니다.

회전했을 때 잘못된 시스템 계산 행 높이를 얻었습니다 (43.5는 실제 높이보다 훨씬 작습니다). 다음과 같습니다.

"<NSLayoutConstraint:0x7bc2b2c0 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7bc37f30(43.5)]>"

단순한 경고가 아닙니다. 테이블 뷰 셀의 레이아웃이 끔찍합니다. 모든 텍스트가 한 텍스트 줄에 겹칩니다.

다음 줄이 내 문제를 마술처럼 “수정”한다는 사실에 놀랐습니다 (자동 레이아웃은 아무것도 불평하지 않고 화면에 예상 한 것을 얻습니다).

myTableView.estimatedRowHeight = 2.0; // any number but 2.0 is the smallest one that works

이 줄의 유무에 관계없이 :

myTableView.rowHeight = UITableViewAutomaticDimension; // by itself this line only doesn't help fix my specific problem

답변

경고 메시지가 (아래 ) 깨져야한다고 말하는 제약 조건의 값 중 하나에 우선 순위 를 지정하여 경고가 사라질 수있었습니다 "Will attempt to recover by breaking constraint". 우선 순위를보다 큰 것으로 설정 49하면 경고가 사라지는 것으로 보입니다 .

나에게 이것은 내 제약 조건을 바꾸는 것을 의미했다.

@"V:|[contentLabel]-[quoteeLabel]|"

에:

@"V:|-0@500-[contentLabel]-[quoteeLabel]|"

사실, 나는 그 제약 조건의 요소에 우선 순위를 추가 할 수 있으며 작동합니다. 어느 것이 중요하지 않은 것 같습니다. 내 세포가 적절한 높이로 끝나고 경고가 표시되지 않습니다. 예를 들어 Roger @500388높이 값 제약 조건 바로 뒤에 추가하십시오 (예 🙂 388@500.

왜 이것이 효과가 있는지 잘 모르겠지만 조금 조사했습니다. 에서 NSLayoutPriority 열거 , 나타납니다 NSLayoutPriorityFittingSizeCompression우선 순위입니다 50. 해당 우선 순위 레벨에 대한 문서는 다음과 같습니다.

fittingSize 메시지를 뷰로 보내면 뷰의 내용에 대해 가장 작은 크기가 계산됩니다. 이 계산에서 뷰가 가능한 작게되기를 원하는 우선 순위 레벨입니다. 꽤 낮습니다. 일반적으로 정확하게이 우선 순위로 제한하는 것은 적절하지 않습니다. 당신은 더 높거나 더 낮아지기를 원합니다.

설명서를 참조에 대한 fittingSize메시지를 읽습니다 :

보유하고있는 구속 조건을 만족하는 뷰의 최소 크기입니다. (읽기 전용)

AppKit은이 속성과 뷰가 유지하는 모든 제약 조건을 고려하고 뷰를 가능한 작게 만들기위한 기본 설정을 만족시키는 것을 고려하여이 속성을 뷰에 사용 가능한 최상의 크기로 설정합니다. 이 속성의 크기 값은 음수가 아닙니다.

나는 그것을 넘어서지 않았지만 이것이 문제가있는 곳과 관련이 있다는 것이 의미가있는 것 같습니다.


답변

사용자 지정 셀 또는 헤더를 사용하는 동안 시간의 99.9 %는 UITableViews테이블이 처음로드 될 때 충돌이 발생합니다. 일단로드되면 일반적으로 충돌이 다시 나타나지 않습니다.

이것은 대부분의 개발자가 일반적으로 고정 된 높이 또는 앵커 구속 조건을 사용하여 셀 / 헤더의 요소를 레이아웃하기 때문에 발생합니다. 충돌은 UITableView첫 번째로드 / 배치시 셀의 높이를 0으로 설정 하기 때문에 발생 합니다. 이는 분명히 자신의 제약 조건과 충돌합니다. 이 문제를 해결하려면 고정 된 높이 구속 조건을 우선 순위가 낮은 ( .defaultHigh)로 설정하십시오. 콘솔 메시지를주의 깊게 읽고 레이아웃 시스템이 어떤 제약을 가하기로 결정했는지 확인하십시오. 일반적으로 우선 순위를 변경해야합니다. 다음과 같이 우선 순위를 변경할 수 있습니다.

let companyNameTopConstraint = companyNameLabel.topAnchor.constraint(equalTo: companyImageView.bottomAnchor, constant: 15)
    companyNameTopConstraint.priority = .defaultHigh

NSLayoutConstraint.activate([
            companyNameTopConstraint,
           the rest of your constraints here
            ])

답변

나는 가짜를 제거하여이 오류를 해결 할 수있었습니다 cell.layoutIfNeeded()내에서 가지고 있음을 tableViewcellForRowAt방법.


답변

제약 조건을 업데이트하도록 테이블 뷰에 알리는 대신 셀을 다시로드하십시오.

[tableView beginUpdates];

[_briefCell collapse:!_showFullBriefText];

[tableView reloadRowsAtIndexPaths:@[[tableView indexPathForCell:_briefCell]] withRowAnimation:UITableViewRowAnimationNone];

[tableView endUpdates];

UIView-Encapsulated-Layout-Height 아마도 해당 시점의 셀 제약 조건에 따라 초기로드 중 셀에 대해 테이블 ​​뷰가 계산 한 높이 일 것입니다.


답변

또 다른 가능성 :

자동 레이아웃을 사용하여 셀 높이 (contentView의 높이, 대부분 아래와 같은 시간)를 계산하고 uitableview 구분 기호가있는 경우 셀 높이를 반환하려면 구분 기호 높이를 추가해야합니다. 정확한 높이를 얻으면 자동 레이아웃 경고가 표시되지 않습니다.

- (CGFloat)calculateHeightForConfiguredSizingCell:(UITableViewCell *)sizingCell {
   [sizingCell setNeedsLayout];
   [sizingCell layoutIfNeeded];
   CGSize size = [sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
   return size.height; // should + 1 here if my uitableviewseparatorstyle is not none

}