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


104

프로그래밍 방식으로 자동 레이아웃 제약 조건을 사용하여 사용자 지정 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에서만 발생하는지 이해하는 데 깊은 관심이 있습니다.


사용자 지정 셀 높이가 어떻게 설정되어 있습니까?
Mike Pollard 2013 년

내 사용자 지정 셀 높이가 90으로 설정되어 있습니다
Alexis

동료가 어제 같은 문제를 겪었지만 기본 너비 는 320 (iPad 앱의 경우)입니다.
jrturton

여기에 동일한 문제를 보여주는 샘플 프로젝트가 있습니다. github.com/Alex311/TableCellWithAutoLayout 여기에 대한 몇 가지 관찰 내용이 있습니다. github.com/Alex311/TableCellWithAutoLayout/commit/…
smileyborg

같은 오류가 발생했지만 사용자 지정 셀의 높이를 찾는 데 사용하던 추가 프로토 타입 셀을 초기화하지 않았기 때문입니다.
Steve Moser

답변:


132

나는 또한이 문제가 있었다 .. 그것은 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;
}

이것은 일 감사합니다. 편집 스타일을 사용하면 어떤 일이 발생할 수 있습니까?
Alexis

11
@ L14M333 여기 에이 주석에 게시 한 코드를 참조하십시오. 기본적으로 self.contentView.bounds = CGRectMake(0, 0, 99999, 99999);제약 조건을 추가하기 전에 문제를 해결할 수 있도록 설정할 수 있어야합니다 .
smileyborg

2
autoresizingMask가 나를 위해 작동하지 않습니다. 초기 제약 조건이 사라졌지 만 새로운 3 개가 추가되었습니다. "<NSAutoresizingMaskLayoutConstraint : 0x8b79740 h =-&-v =-&-UITableViewCellContentView : 0x8b44010.height == UITableViewCellScrollView : 0x8b4a130.height>", "<NSAutoresizingMaskLayoutConstraint : 0x8b7b9f0 h =-&-v =-&-UITableViewCellScrollView : 0x8b4a130.height == LibraryCell : 0x8ac19d0.height>", "<NSAutoresizingMaskLayoutConstraint : 0xCell :-& Librint : 0xCell :-& 0x8ac19d0 (0)]> "
catamphetamine 2014 년

1
나에게도 효과가 있습니다. 1 시간 정도 고생했습니다! 감사! <3
mokagio

2
다른 자동 레이아웃 문제 (iOS 7 / iOS 8)를 제거한 후을 사용 self.contentView.bounds = CGRectMake(0, 0, 99999, 99999);하는 것만 큼 효과적 이라는 것을 알았습니다 self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;. updateConstraints내 콘텐츠 뷰에 ​​제약을 추가하기 전에 이것을 넣었습니다 .
테스트

35

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에서만 실행될 때 발생합니다.


1
이것이 최선의 답변이거나 적어도 저에게 가장 적합한 솔루션입니다. My Cell (자동 레이아웃 규칙)은 XCode6을 사용하는 iOS8에서 훌륭하게 작동했고 XCode 5를 사용하는 iOS7 및 6에서 훌륭하게 작동했습니다. XCode를 XCode6로 업데이트했는데 더 이상 iOS6 및 7에서 작동하지 않습니다. 그래서 감사합니다 !!!!
xarly

이것은 더 이상 Xcode 6.1에서 문제가되지 않습니다. 또한, NSFoundationVersionNumber을 사용하지 마십시오 참조하십시오 nshipster.com/swift-system-version-checking
onmyway133

1
@ onmyway133 : Xcode 6.1에서 더 이상 문제가되지 않는 이유는 무엇입니까? Xcode 6.1 및 iOS 8.1 SDK를 사용하더라도 여전히 문제가 있습니다. 이 문제는 iOS 7에서만 발생합니다. 경계를 변경하거나 자동 크기 조정 마스크를 설정하면 문제가 해결됩니다. 그러나 나는 가장 많이 득표 한 답변이나 의견에 명시된 접근 방식을 사용했습니다.
테스트

네, 이것은 3 시간 동안 인터넷 검색을 기반으로 한 최고의 답변입니다. 다른 유사한 "솔루션"은 cell.contentView.autoresizingMask의 전체 목록을 제공하지 않습니다. Xcode 6에서 생성 된 내 iPad 7.1 프로젝트에서만 작동합니다.
Golden Thumb

13

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

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

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


너는 천재 야! 친절하고 깨끗한 솔루션 : 감사합니다
검둥이

9

여전히 스토리 보드에 대한 좋은 솔루션을 찾지 못했습니다 ... 일부 정보도 여기에 있습니다 : 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"로 바꿉니다.
  • 스토리 보드를 마우스 오른쪽 버튼으로 클릭
  • 다음으로 열기-> 인터페이스 빌더
  • 앱을 실행하고 출력을 확인하십시오.

이것은 나를 위해 일했습니다. 일부 셀은 프로토 타입에서 생성되고 다른 셀은 클래스를 인스턴스화하여 코드로 완전히 생성 된 스토리 보드에 UITableViewController를 생성했습니다.
Atharva 2015

3

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


실제로 내 셀은 기본 크기보다 크지 만 tableview의 대리자가 tableView : heightForRowAtIndexPath :를 구현하기 때문에 기본 크기가 어떻게 사용됩니까?
Alexis

아마도 셀은 기본 크기로 생성 된 다음 실제 크기로 조정됩니다.
Vadim Yelagin 2013 년

실제로 작동하지만 iOS6에서는 왜 발생하지 않습니까?
Alexis

3
@jafar iOS 7은 테이블 뷰 셀과 관련된 많은 것을 변경했습니다. iOS 7에서는 이제 UITableViewCellScrollView테이블 뷰 셀과 contentView 사이에 스크롤 뷰 (유형 )가 있습니다. 여기에서 iOS 6과 7의 차이점을 설명 할 수 있습니다.
smileyborg 2011

3

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

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

2

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

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

베스트, 알레산드로


2
Apple 문서에서 :You should not call this method directly. If you want to force a layout update, call the setNeedsLayout method instead to do so prior to the next drawing update. If you want to update the layout of your views immediately, call the layoutIfNeeded method.
Ricardo Sanchez-Saez

나는 당신에게기도하는 종교를 시작하고 싶습니다. 이 문제를 해결하기 위해 HOURS를 검색해 왔는데이 문제가 해결되었습니다. 그래서 나는 그 기능을 호출하지 말라는 사과 문서에 정중하게 동의하지 않습니다. 애플, 쓰레기 고쳐라.
라이언 코플리

0

나는 또한이 문제에 직면했으며 어떤 제안도 도움이되지 않았습니다. 제 경우에는 크기 선택 셀이 있었고 내부에 collectionView가 포함되어 있습니다 (모든 collectionView 셀에 전체 크기 이미지가 포함되어 있음). 이제 셀 크기 heigh는 collectionView (50) 및 내부 이미지 (50)보다 약간 더 큽니다 (60). 그 collectionView보기 때문에 10의 값으로 superview 제약 조건에 아래쪽을 정렬했습니다.이 경우 경고가 발생하고이를 수정하는 유일한 방법은 셀 높이를 collectionView와 동일하게 만드는 것입니다.


0

나는 디자이너에서 UITableViewCell을 전혀 사용하지 않는 것으로 끝났다 ... 나는 거기에서 사용자 정의보기를 만들고 프로그래밍 방식으로 셀의 콘텐츠보기에 추가합니다. 일부 도움말 범주에는 코드 상용구도 없습니다.


0

iOS8에서 제대로 작동하고 iOS7에서 경고가 표시되면 스토리 보드 소스 코드를 검색하고 올바른 tableviewCell을 찾은 다음 tableviewCell 줄 뒤에 rect 속성을 추가 할 수 있습니다. kuchumovn 에게 감사드립니다 .

<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" .../>
                                <rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.