[ios] UITableViewCell의 iOS7에서 자동 레이아웃 제약 문제

프로그래밍 방식으로 자동 레이아웃 제약 조건을 사용하여 사용자 지정 UITableView 셀을 레이아웃하고 있으며 셀 크기를 올바르게 정의하고 있습니다. tableView:heightForRowAtIndexPath:

iOS6에서 잘 작동 하고 iOS7에서도 잘 보입니다.

하지만 iOS7에서 앱을 실행할 때 콘솔에 표시되는 메시지는 다음과 같습니다.

Break on objc_exception_throw to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2013-10-02 09:56:44.847 Vente-Exclusive[76306:a0b] 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:0xac4c5f0 V:|-(15)-[UIImageView:0xac47f50]   (Names: '|':UITableViewCellContentView:0xd93e850 )>",
        "<NSLayoutConstraint:0xac43620 V:[UIImageView:0xac47f50(62)]>",
        "<NSLayoutConstraint:0xac43650 V:[UIImageView:0xac47f50]-(>=0)-[UIView:0xac4d0f0]>",
        "<NSLayoutConstraint:0xac43680 V:[UIView:0xac4d0f0(1)]>",
        "<NSLayoutConstraint:0xac436b0 V:[UIView:0xac4d0f0]-(0)-|   (Names: '|':UITableViewCellContentView:0xd93e850 )>",
        "<NSAutoresizingMaskLayoutConstraint:0xac6b120 h=--& v=--& V:[UITableViewCellContentView:0xd93e850(44)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0xac43650 V:[UIImageView:0xac47f50]-(>=0)-[UIView:0xac4d0f0]>

그리고 실제로 그 목록에 내가 원하지 않는 제약 조건 중 하나가 있습니다.

"<NSAutoresizingMaskLayoutConstraint:0xac6b120 h=--& v=--& V:[UITableViewCellContentView:0xd93e850(44)]>"

translatesAutoresizingMaskIntoConstraints속성 contentView을 NO =>로 설정할 수 없으므로 전체 셀이 엉망이 될 것입니다.

44는 기본 셀 높이이지만 테이블 뷰 델리게이트에서 사용자 지정 높이를 정의했는데 왜 셀 contentView에이 제약이 있습니까? 원인은 무엇입니까?

iOS6에서는 발생하지 않으며 iOS6 및 iOS7 모두에서 모든 것이 잘 보입니다.

내 코드는 꽤 커서 여기에 게시하지 않겠지 만 필요한 경우 언제든지 pastebin을 요청하십시오.

수행 방법을 지정하려면 셀 초기화에서 :

  • 모든 레이블, 버튼 등을 만듭니다.
  • 나는 그들의 translatesAutoresizingMaskIntoConstraints속성을 NO로 설정했습니다.
  • 나는 그들을 contentView셀의 하위보기로 추가합니다.
  • 나는에 제약을 추가합니다 contentView

나는 이것이 왜 iOS7에서만 발생하는지 이해하는 데 깊은 관심이 있습니다.



답변

나는 또한이 문제가 있었다 .. 그것은 layoutSubviews호출 될 때까지 contentView의 프레임이 업데이트되지 않는 것으로 보이지만 {0, 0, 320, 44}, 제약 조건이 평가 될 때 설정된 contentView의 프레임을 남겨두고 셀의 프레임이 더 일찍 업데이트 됩니다.

contentView를 자세히 살펴보면 autoresizingMask가 더 이상 설정되지 않는 것 같습니다.

뷰를 제한하기 전에 autoresizingMask를 설정하면이 문제를 해결할 수 있습니다.

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];
    if (self)
    {
        self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
        [self loadViews];
        [self constrainViews];
    }
    return self;
}


답변

iOS 8 SDK를 사용하는 iOS 7에서 UITableViewCell 및 UICollectionViewCell에 문제가있는 것 같습니다.

셀이 다음과 같이 재사용 될 때 셀의 contentView를 업데이트 할 수 있습니다.

정적 UITableViewController의 경우 :

#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];

    if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1)
    {
        cell.contentView.frame = cell.bounds;
        cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin |UIViewAutoresizingFlexibleTopMargin |UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
    }

    //your code goes here

    return cell;
}

#endif
#endif

정적 테이블 뷰 컨트롤러는 깨지기 쉽고 일부 데이터 소스 또는 deletegate 메서드를 구현하면 쉽게 손상 될 수 있으므로이 코드가 iOS 7에서만 컴파일되고 실행되는지 확인하는 검사가 있습니다.

표준 동적 UITableViewController와 유사합니다.

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellID = @"CellID";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];

    if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1)
    {
        cell.contentView.frame = cell.bounds;
        cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin |UIViewAutoresizingFlexibleTopMargin |UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
    }
    //your code goes here       
    return cell;
}

이 경우이 메서드를 구현해야하므로 컴파일 추가 검사가 필요하지 않습니다.

아이디어는 두 경우와 UICollectionViewCell에 대해 동일합니다.이 스레드에 설명 된대로 : Storyboard 프로토 타입 셀 (Xcode 6, iOS 8 SDK)에서 UICollectionViewCell contentView 프레임의 자동 크기 조정 문제는 iOS 7에서만 실행될 때 발생합니다.


답변

셀이 재사용되고 내용에 따라 높이가 변경 될 수 있으므로 일반적으로 간격의 우선 순위를 필요한 것보다 작게 설정하는 것이 좋습니다.

귀하의 경우에는 UIImageView의 간격이 상단에 15이고 하단 뷰의 간격이 하단에 0입니다. 이러한 제약 조건의 우선 순위를 1000이 아닌 999로 설정하면 제약 조건이 필요하지 않으므로 앱이 충돌하지 않습니다.

layoutSubviews 메서드가 호출되면 셀의 높이가 정확하고 제약 조건이 정상적으로 충족 될 수 있습니다.


답변

여전히 스토리 보드에 대한 좋은 솔루션을 찾지 못했습니다 … 일부 정보도 여기에 있습니다 :
https://github.com/Alex311/TableCellWithAutoLayout/commit/bde387b27e33605eeac3465475d2f2ff9775f163#commitcomment-4633188

그들이 조언 한 것에서 :

self.contentView.bounds = CGRectMake(0, 0, 99999, 99999);

내 솔루션을 유도했습니다.

  • 스토리 보드를 마우스 오른쪽 버튼으로 클릭
  • 다음으로 열기-> 소스 코드
  • 거기에서 문자열 “44”검색
  • 그것은 같을거야

.

<tableView hidden="YES" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="none" allowsSelection="NO" rowHeight="44" ...
    <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="ChatMessageCell" id="bCG-aU-ivE" customClass="ChatMessageCell">
        <rect key="frame" x="0.0" y="22" width="320" height="44"/>

.

  • rowHeight = “44”를 rowHeight = “9999”로, height = “44”를 height = “9999”로 바꿉니다.
  • 스토리 보드를 마우스 오른쪽 버튼으로 클릭
  • 다음으로 열기-> 인터페이스 빌더
  • 앱을 실행하고 출력을 확인하십시오.

답변

기본 셀 높이를 늘리십시오. 문제는 셀의 내용이 기본 (초기) 셀 크기보다 커서 셀 크기가 실제 크기로 조정될 때까지 일부 비 음성 제약 조건을 위반하는 것 같습니다.


답변

보기의 우선 순위를 750보다 크고 1000보다 작게 설정하면 해결할 수 있습니다.

"<NSLayoutConstraint:0xac43620 V:[UIImageView:0xac47f50(62)]>",


답변

나는 같은 문제가 있었다. 위의 다른 사용자를 기반으로 한 내 솔루션 :

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
        // initialize my stuff
        [self layoutSubviews]; // avoid debugger warnings regarding constraint conflicts
    }
    return self;
}

베스트, 알레산드로