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

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 **/



답변

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]
}


답변

같은 문제가 발생하여 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의 답변을 제공하는 것이 합리적이므로 나중에 시도해 보겠습니다.


답변

동일한 문제가 발생했으며 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;
  }
}


답변

또 다른 해결책은 -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;
}

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


답변

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)]];


답변

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에서 빌드하는 데 필요한 콘텐츠보기에 자동 크기 조정 마스크를 추가했기 때문에 문제가 해결되었습니다.


답변

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

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

  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.