Storyboard 프로토 타입 셀 (Xcode 6, iOS 8 SDK)에서 UICollectionViewCell contentView 프레임의 자동 크기 조정 문제는 iOS 7에서만 실행될 때 발생합니다.


158

Xcode 6 Beta 3, iOS 8 SDK를 사용하고 있습니다. Swift를 사용하여 Target iOS 7.0을 빌드하십시오. 아래 스크린 샷으로 내 문제를 단계별로 참조하십시오.

Storyboard에 UICollectionView가 있습니다. 중앙에 1 개의 레이블을 포함하는 1 개의 프로토 타입 UICollectionViewCell (자동 크기 조정 규칙 없음). 보라색 배경은 내가 추측하는 Cell에 의해 런타임에 생성되는 contentView를 표시하는 것입니다. 해당 뷰는 결국 내 UICollectionViewLayoutDelegate를 기반으로 적절하게 크기가 조정되지만 iOS 7에서는 그렇지 않습니다. Xcode 6을 사용하고 있으며 문제는 iOS 7에서만 발생합니다.

iOS 8에서 앱을 빌드 할 때 모든 것이 괜찮습니다.

참고 : 자주색은 contentView 이고 파란색은 둥근 모서리가있는 UIButton입니다.

http://i.stack.imgur.com/uDNDY.png

그러나 iOS 7에서는 Cell 내부의 모든 subView가 갑자기 (0,0,50,50) 프레임으로 축소되고 더 이상 내 자동 크기 조정 규칙을 따르지 않습니다.

http://i.stack.imgur.com/lOZH9.png

이것이 iOS 8 SDK 또는 Swift 또는 Xcode의 버그라고 가정합니까?


업데이트 1 : 이 문제는 공식 Xcode 6.0.1에 여전히 존재합니다! 가장 좋은 해결 방법은 셀의 cellForItem에 프레임을 설정하여 아래에 제안한 KoCMoHaBTa와 같습니다 (하지만 셀을 하위 클래스로 분류해야 함). 이것은 iOS 8 SDK와 iOS 7 사이의 비 호환성임이 밝혀졌습니다 (Apple에서 인용 한 아래 ecotax의 답변 확인).

업데이트 2 : 이 코드를 cellForItem 의 시작 부분에 붙여 넣으면 괜찮을 것입니다.

/** Xcode 6 on iOS 7 hot fix **/
cell.contentView.frame = cell.bounds;
cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
/** End of Xcode 6 on iOS 7 hot fix **/

1
이 문제는 Xcode 6 Beta 5에서도 여전히 존재한다는 것을 알게되었습니다. 누구도 이것을 경험 했습니까?
thkeen

2
나는 지금 내 프로젝트에서 이것으로 어려움을 겪고 있습니다. Xcode 5를 사용하여 빌드 된 iOS 7 및 iOS 8은 괜찮아 보입니다. Xcode 6 베타 6을 사용하여 빌드 된 iOS 8은 괜찮아 보입니다. Xcode 6 베타 6을 사용하여 빌드 된 iOS 7에 설명하는 문제가 있습니다. Reveal을 사용하면 UICollectionViewCell의 크기가 적절하게 조정되었음을 알 수 있습니다. 그러나 셀의 contentView는 부모이지만 UICollectionViewCell에는 Autoresize Subviews가 켜져 있지만 크기가 조정되지 않았습니다. contentView의 크기는 스토리 보드의 크기로 설정됩니다. 이 프로젝트에서 자동 레이아웃을 사용하지 않습니다. 내 프로젝트는 완전히 객관적입니다.
Del Brown

2
이 문제는 Xcode 6 / iOS 8 GM 시드 기준으로 여전히 존재한다고 덧붙이고 싶었습니다. @DanielPlamann의 대답 contentView은 문제를 해결하기 위해 잘 작동합니다. iOS 8에서 Apple은 Interface Builder에서 생성 될 때 셀 콘텐츠 뷰가 처리되는 방식을 변경했다고 생각합니다 (어쨌든 여전히 약간의 블랙 박스입니다). 그러나 iOS 7을 대상으로 할 때 동작이 변경된다는 사실은 분명히 버그입니다.
Stuart

Xcode 6 GM, 자동 레이아웃 및 펜촉 기반 셀과 동일합니다. contentView가장자리를 셀 가장자리 에 고정하여 고정합니다 .
sergiou87 2014 년

3
xcode 6.1을 다운로드했지만 시뮬레이터에서 여전히 동일한 문제가 나타납니다.
Haitao Li

답변:


169

contentView가 손상되었습니다. awakeFromNib에서도 수정할 수 있습니다.

ObjC :

- (void)awakeFromNib {

    [super awakeFromNib];

    self.contentView.frame = self.bounds;
    self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
}

Swift3 :

override func awakeFromNib() {
    super.awakeFromNib()

    self.contentView.frame = self.bounds
    self.contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
}

3
self.contentView.frame = self.bounds없이 트릭을 했습니까? 내가 필요하다고 생각해? 어쨌든 감사합니다!
Michal Shatz 2014 년

안녕하세요 Michal, 동의합니다. 하지만 100 % 확실히하기 위해서는 다음 iOS에서 추가하는 것이 더 좋을 것이라고 생각합니다.
Igor Palaguta 2014 년

5
이 답변이 마음에 들지만 [super awakeFromNib]를 호출해야합니다. 또한 이러한 크기 조정 마스크를 추가하는 것이 iOS8의 기본 동작에 어떤 영향을 미치는지 잘 모르겠 기 때문에 iOS 7.1 이하에 대한 검사를 추가 할 생각입니다.
GingerBreadMane 2014 년

펜촉이나 스토리 보드를 사용하지 않는 경우 applyLayoutAttributes에 넣어도 작동합니다.
cetcet

이것은 나를 위해 작동하지 않습니다. Autolayout을 사용하고 있지 않습니다 !! 도움이 필요하십니까?
thatzprem

61

같은 문제가 발생하여 Apple DTS에 도움을 요청했습니다. 그들의 대답은 다음과 같습니다.

iOS 7에서 셀의 콘텐츠 뷰는 자동 크기 조정 마스크를 통해 자체적으로 크기가 조정되었습니다. iOS 8에서는 이것이 변경되어 셀이 자동 크기 조정 마스크 사용을 중지하고 layoutSubviews에서 콘텐츠보기 크기를 조정하기 시작했습니다. 펜촉이 iOS 8에서 인코딩 된 다음 iOS 7에서 디코딩되면 자동 크기 조정 마스크가없고 자체 크기를 조정할 수있는 다른 방법이없는 콘텐츠보기가 제공됩니다. 따라서 셀의 프레임을 변경하면 콘텐츠보기가 따라 오지 않습니다.

iOS 7에 다시 배포되는 앱은 콘텐츠보기 자체의 크기를 조정하거나 자동 크기 조정 마스크를 추가하거나 제약 조건을 추가하여이 문제를 해결해야합니다.

이것은 XCode 6의 버그가 아니라 iOS 8 SDK와 iOS 7 SDK 간의 비 호환성이라는 것을 의미한다고 생각합니다 .Xcode 6으로 업그레이드하면 자동으로 iOS 8 SDK를 사용하기 시작하기 때문입니다.

이전에 언급했듯이 Daniel Plamann이 설명한 해결 방법이 저에게 효과적입니다. Igor Palaguta와 KoCMoHaBTa가 설명하는 것은 더 단순 해 보이며 Apple DTS의 답변을 제공하는 것이 합리적이므로 나중에 시도해 보겠습니다.


이것은 흥미롭지 만 여전히 그들이 그것을 고치기를 바랍니다. 이 동작은 iPhone 6 지원을 추가 한 Xcode 6 GM에서만 도입되었습니다. 이전 베타에서는 잘 작동했습니다. 나는 그것을 발견하고 예상대로 작동 한 후에 프로젝트를 이전 베타로 되돌리기도했다. 모두가이 문제에 대해 Apple에 버그를 제출하기를 바랍니다.
arton

@arton DTS에 도움을 요청한 날 버그 보고서를 제출했습니다. 18312246의 복제로 마감되었습니다. 이것이 얼마나 도움이되는지 확실하지 않습니다.
ecotax 2014 년

나는 ContentView의 크기를 조정하여 해결 방법을 사용했으며 나를 위해 일했습니다. -(CGSize) collectionViewContentSize {return CGSizeMake (self.collectionView.bounds.size.width, self.collectionView.bounds.size.height); }
Jesús Hurtado 2015

60

동일한 문제가 발생했으며 Apple이 다음 Xcode 버전에서이 문제를 해결하기를 바랍니다. 한편 나는 해결 방법을 사용합니다. 내 UICollectionViewCell하위 클래스 layoutSubviews에서 collectionViewCell크기 가 크기와 다른 경우 수동으로 contentView를 재정의 하고 크기를 조정했습니다 .

- (void)layoutSubviews
{
  [super layoutSubviews];

  BOOL contentViewIsAutoresized = CGSizeEqualToSize(self.frame.size, self.contentView.frame.size);

  if( !contentViewIsAutoresized) {
    CGRect contentViewFrame = self.contentView.frame;
    contentViewFrame.size = self.frame.size;
    self.contentView.frame = contentViewFrame;
  }
}

네 비슷한 작업을 사용했지만 cellForItem / cellForRow에서도 작동합니다.
thkeen 2014 년

1
이것이 최상의 솔루션입니다. 이것을 cellForItem / cellForRow에 추가하면 장치를 회전하고 셀 크기가 변경되면 이상한 아티팩트가 발생합니다.
spybart 2014 년

안녕하세요! 이 코드에 문제가 있습니다. 처음으로 부울 contentViewIsAutoresized는 스토리 보드 또는 프로토 타입 셀에서로드되는 경우 true가됩니다. reloadData를 수행하는 경우에만 두 번째로 정확합니다. 따라서 실제로 크기를 확인할 필요가 없습니다. 대신 다음을 수행하십시오. self.contentView.frame = self.bounds;
thkeen

확인 됨 : layoutSubviews는 셀이 반환 된 후에 만 ​​호출되므로 cellForItem 또는 cellForRow에서 수행해야합니다. 그림 그리기와 같이 그 전에하는 모든 작업은 잘못 계산됩니다.
thkeen

1
흠, [cell layoutIfNeeded];cellForItem 또는 cellForRow 에 배치 하는 것이 더 낫 습니까?
wtorsi

38

또 다른 해결책은 -collectionView:cellForItemAtIndexPath:다음과 같이 contentView의 크기와 자동 크기 조정 마스크를 설정하는 것입니다 .

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {

     static NSString *cellID = @"CellID";

     UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellID forIndexPath:indexPath];

     // Set contentView's frame and autoresizingMask
     cell.contentView.frame = cell.bounds;
     cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin |UIViewAutoresizingFlexibleTopMargin |UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;

     // Your custom code goes here

     return cell;
}

자동 크기 조정 마스크가 제약 조건으로 변환되기 때문에 자동 레이아웃에서도 작동합니다.


2
이는 서브 클래 싱없이 모든 셀 유형에서 작동하고 컬렉션보기에서 둘 이상의 셀 유형을 사용할 때 여러 위치에서 변경할 필요가 없기 때문에 탁월한 솔루션입니다.
2014 년

6

Xcode 6.0.1에서 UICollectionViewCell 용 contentView가 iOS7 장치에서 손상되었습니다. awakeFromNib 또는 init 메서드에서 UICollectionViewCell 및 해당 contentView에 적절한 제약 조건을 추가하여 수정할 수도 있습니다.

        UIView *cellContentView = self.contentView;
        cellContentView.translatesAutoresizingMaskIntoConstraints = NO;

        [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[cellContentView]|"
                                                                     options:0
                                                                     metrics:0
                                                                       views:NSDictionaryOfVariableBindings(cellContentView)]];
        [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[cellContentView]|"
                                                                     options:0
                                                                     metrics:0
                                                                       views:NSDictionaryOfVariableBindings(cellContentView)]];

지금은이 작업 만 작동합니다. IOS 8에서만 수행해야하며 대기열에서 빼기 전에 호출해야합니다! 다중 선택이 시각적으로해야 같은 ... 작동하지 않습니다 때문에 그러나 이것은 또한 이상적인 해결책이 아니다
Renetik

가장 좋은 방법은 실제로 자동 레이아웃을 사용하는 것입니다.이 버그를 사용하면 간단한 경우에 자동 레이아웃 이벤트를 사용하여 아이러니하게 시간을 절약 할 수 있습니다.
Renetik

마스크가 작동하지 않습니다. 그러나 제약 조건을 설정하면 작동합니다!
엔트로피 드

4

Xcode가 xib 파일을 nib 형식으로 컴파일하는 방법에 대한 Xcode 6 GM의 버그로 인해 언급 된 다른 해결 방법이 없으면 제대로 작동하지 않습니다. 100 % 확실하게 Xcode와 관련이 있고 런타임과 관련이 없다고 말할 수는 없지만, 매우 확신합니다.이를 어떻게 보여줄 수 있는지는 다음과 같습니다.

  1. Xcode 5.1에서 애플리케이션을 빌드하고 실행합니다.
  2. 시뮬레이터 애플리케이션의 디렉토리로 이동하여 문제가있는 xib 용으로 컴파일 된 .nib 파일을 복사하십시오.
  3. Xcode 6 GM에서 애플리케이션을 빌드하고 실행합니다.
  4. 응용 프로그램을 중지하십시오.
  5. 새로 빌드 된 애플리케이션의 시뮬레이터 폴더에있는 .nib 파일을 Xcode 5.1을 사용하여 만든 .nib 파일로 바꿉니다.
  6. Xcode가 아닌 시뮬레이터에서 앱을 다시 시작하십시오.
  7. 해당 .nib에서로드 된 셀이 예상대로 작동합니다.

이 질문을 읽는 모든 사람이 Apple에 레이더를 제출하기를 바랍니다. 이것은 큰 문제이며 최종 Xcode 릴리스 전에 해결해야합니다.

편집 : ecotax의 게시물비추어 볼 때 iOS 8과 iOS 7에서 빌드 사이의 동작 차이가 확인되었지만 버그가 아니라고 말하고 싶었습니다. 내 해킹은 iOS 7에서 빌드하는 데 필요한 콘텐츠보기에 자동 크기 조정 마스크를 추가했기 때문에 문제가 해결되었습니다.


합법적으로 GM 버전과 다른 xCode를 릴리스 할 수 있는지 잘 모르겠습니다
Mabedan 2014 년

하하 감옥에 갈까요? = P 그러나 모든 진지함에서 그들은 할 수 있습니다. 기억 나지 않는다면 Mavericks를위한 여러 GM 버전이 있습니다. 너무 흔하지는 않지만 일어날 수 있습니다.
Acey 2014 년

4

이 포스트 작업의 답변, 내가 이해하지 못한 것은 그것이 작동하는 이유 입니다.

첫째, 두 가지 "규칙"이 있습니다.

  1. 프로그래밍 방식으로 생성 된 뷰 (예 :)의 [UIView new]경우 속성 translatesAutoresizingMaskIntoConstraints은 다음과 같이 설정됩니다.YES
  2. AutoLayout이 활성화 된 인터페이스 빌더에서 생성 된 뷰는 속성이 translatesAutoresizingMaskIntoConstraints다음과 같이 설정됩니다.NO

두 번째 규칙은 제약 조건을 정의하지 않은 최상위 뷰에는 적용되지 않는 것 같습니다. (예 : 콘텐츠보기)

Storyboard 셀을 볼 때 셀에 contentView노출 되지 않은 것을 알 수 있습니다. 우리는 contentView애플이 "통제"하는 것이 아닙니다 .

스토리 보드 소스 코드를 자세히 살펴보고 contentView셀이 어떻게 정의 되는지 확인하세요 .

<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">

이제 셀의 하위보기 ( translatesAutoresizingMaskIntoConstraints="NO") :

<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="NaT-qJ-npL" userLabel="myCustomLabel">

에는로 설정되어 contentView있지 않습니다 . 게다가 @ecotax가 말한 것 때문에 레이아웃 정의가 부족합니다 .translatesAutoresizingMaskIntoConstraintsNO

를 살펴보면 contentView자동 크기 조정 마스크가 있지만 정의는 없습니다. <autoresizingMask key="autoresizingMask"/>

따라서 두 가지 결론이 있습니다.

  1. contentView translatesAutoresizingMaskIntoConstraints로 설정됩니다 YES.
  2. contentView 레이아웃의 정의가 부족합니다.

이것은 우리가 논의 된 두 가지 해결책으로 이어집니다.

에서 자동 크기 조정 마스크를 수동으로 설정할 수 있습니다 awakeFromNib.

self.contentView.frame = cell.bounds;
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

아니면을 설정할 수 있습니다 contentView translatesAutoresizingMaskIntoConstraintsNO있는 awakeFromNib과에 제약 조건을 정의 - (void)updateConstraints.


4

이것은 수락 된 @Igor의 답변의 Swift 버전이며 멋진 답변 친구에게 감사드립니다.

먼저 고토 귀하 UICollectionViewCell는 클래스 내에 서브 클래스에 다음 코드를 붙여.

override func awakeFromNib() {
    super.awakeFromNib()
    self.contentView.frame = self.bounds
    self.contentView.autoresizingMask = [.FlexibleHeight, .FlexibleWidth]
}

그건 그렇고 나는 Xcode 7.3.1과 Swift 2.3을 사용하고 있습니다. 솔루션은 완벽하게 작동하는 iOS 9.3에서 테스트되었습니다.

감사합니다. 도움이 되었기를 바랍니다.


죄송합니다 나의 나쁜 영어, 내가 의미 : "마법처럼 작동합니다"
Aznix

@Aznix No issue .. :)
onCompletion

2

신속하게 컬렉션 뷰 셀 하위 클래스에 다음 코드를 배치합니다.

override var bounds: CGRect {
  didSet {
    // Fix autolayout constraints broken in Xcode 6 GM + iOS 7.1
    self.contentView.frame = bounds
  }
}

이것이 제가 찾고 있던 답이었습니다. 이 문제를 해결하기 위해 Objective-C에서 setBounds를 재정의하는 데 사용했습니다 (Swift에서 작성하는 방법을 잘 모르겠 음). :) 주셔서 감사합니다
마 콜리에게

1

contentViewiOS 8 에서도 크기 조정에 문제가 있음을 발견 했습니다.주기의 매우 늦게 배치되는 경향이있어 일시적인 제약 충돌이 발생할 수 있습니다. 이를 해결하기 위해 다음과 같은 방법을 카테고리에 추가했습니다 UICollectionViewCell.

- (void)fixupContentView
{
#if __IPHONE_OS_VERSION_MAX_ALLOWED < 80100
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
    if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1) {
        self.contentView.frame = self.bounds;
        self.contentView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin |UIViewAutoresizingFlexibleTopMargin |UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
    } else {
        [self layoutIfNeeded];
    }
#endif
#endif
}

이 메서드는 셀의 대기열을 뺀 후에 호출해야합니다.


이 메서드가 자동으로 호출되면 이상적입니다. 나는 그것을 좋아하지 않지만 이것은 swizzling으로 할 수 있습니다 dequeueReusableCellWithReuseIdentifier:forIndexPath:.
phatmann 2014 년

Apple은 Xcode 6.1 GM (빌드 6A1042b)의 iOS SDK 버전 8.1에서이 문제를 해결 한 것으로 보입니다. 따라서 8.1 SDK를 사용할 때 실행되지 않도록 위 코드를 업데이트했습니다. 팀이 모두 Xcode 6.1로 이동하면이 해킹을 완전히 제거 할 수 있습니다.
phatmann

1

나는 이것을 고쳤다.

override func layoutSubviews() {
   contentView.superview?.frame = bounds
   super.layoutSubviews()
}

참조 : 여기


-1

해당 컬렉션 뷰 셀의 펜촉에서 "Autoresize subviews"확인란을 선택했는지 확인하십시오. iOS 8과 iOS 7 모두에서 잘 작동합니다.


아니에요. 이것은 임베디드 프로토 타입 셀입니다.
thkeen
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.