iOS 7에서만 실행할 때 Storyboard 프로토 타입 셀 (Xcode 6, iOS 8 SDK)의 UICollectionViewCell contentView 프레임 자동 크기 조정 문제가 발생합니다.
Xcode 6 Beta 3, iOS 8 SDK를 사용하고 있습니다. Swift를 사용하여 대상 iOS 7.0을 빌드하십시오. 아래 스크린 샷과 함께 내 문제를 단계별로 참조하십시오.
스토리 보드에 UICollectionView가 있습니다. 1 중앙에 1 개의 레이블이있는 프로토 타입 UICollectionViewCell (자동 크기 조정 규칙 없음). 자주색 배경은 추측하는 셀에 의해 런타임에 생성되는 contentView를 표시하는 것이 었습니다. 이 뷰의 크기는 결국 UICollectionViewLayoutDelegate에 따라 적절하게 조정되지만 iOS 7에서는 그렇지 않습니다. Xcode 6을 사용하고 있으며 문제는 iOS 7에서만 발생합니다.
iOS 8에서 앱을 빌드하면 모든 것이 정상입니다.
참고 : 자주색은 contentView 이며 파란색은 모서리가 둥근 내 UIButton입니다.
그러나 iOS 7에서는 Cell 내부의 모든 subView가 갑자기 (0,0,50,50) 프레임으로 축소되어 더 이상 내 자동 크기 조정 규칙을 준수하지 않습니다.
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;
}
스위프트 3 :
override func awakeFromNib() {
super.awakeFromNib()
self.contentView.frame = self.bounds
self.contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
}
같은 문제가 발생하여 Apple DTS에 도움을 요청했습니다. 그들의 대답은 다음과 같습니다.
In iOS 7, cells’ content views sized themselves via autoresizing masks. In iOS 8, this was changed, cells stopped using the autoresizing masks and started sizing the content view in layoutSubviews. If a nib is encoded in iOS 8 and then decode it on iOS 7, you’ll have a content view without an autoresizing mask and no other means by which to size itself. So if you ever change the frame of the cell, the content view won’t follow.
Apps being deploying back to iOS 7 will have to work around this by sizing the content view itself, adding autoresizing masks, or adding constraints.
I guess this means that it's not a bug in XCode 6, but an incompatibility between the iOS 8 SDK and iOS 7 SDK, which will hit you if you upgrade to Xcode 6, because it will automatically start using the iOS 8 SDK.
As I commented before, the workaround Daniel Plamann described works for me. The ones described by Igor Palaguta and KoCMoHaBTa look simpler though, and appear to make sense giving Apple DTS' answer, so I'll try those later.
I encountered the same issue and hope that Apple will fix this with the next Xcode version. Meanwhile I use a workaround. In my UICollectionViewCell
subclass I've just overridden layoutSubviews
and resize the contentView manually in case the size differs from collectionViewCell
size.
- (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;
}
}
Another solution is to set the contentView's size and autoresizing masks in -collectionView:cellForItemAtIndexPath:
like the following:
- (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;
}
This works with Auto Layout too, since auto resizing masks are translated to constraints.
In Xcode 6.0.1 contentView for UICollectionViewCell is broken for iOS7 devices. It can be also fixed by adding proper constraints to UICollectionViewCell and its contentView in awakeFromNib or init methods.
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)]];
This will not work correctly without any of the other mentioned workarounds because of a bug in Xcode 6 GM with how Xcode compiles xib files into the nib format. While I cannot say for 100% certainty it is Xcode related and not having to do with runtime, I'm very confident - here's how I can show it:
- Build+Run the application in Xcode 5.1.
- Go to the simulator application's directory and copy the compiled .nib file for the xib you are having issues with.
- Build+Run the application in Xcode 6 GM.
- Stop the application.
- Replace the .nib file in the newly built application's simulator folder with the .nib file created using Xcode 5.1
- Relaunch the app from the simulator, NOT from Xcode.
- Your cell loaded from that .nib should work as expected.
I hope everyone who reads this question will file a Radar with Apple. This is a HUGE issue and needs addressing before the final Xcode release.
Edit: In light of ecotax's post, I just wanted to update this to say it is now confirmed behavior differences between building in iOS 8 vs iOS 7, but not a bug. My hack fixed the issue because building on iOS 7 added the autoresizing mask to the content view needed to make this work, which Apple no longer adds.
The answers in this post work, what I never understood is why it works.
First, there are two "rules":
- For views created programmatically (Ex.
[UIView new]
), the propertytranslatesAutoresizingMaskIntoConstraints
is set toYES
- Views created in interface builder, with AutoLayout enabled, will have the property
translatesAutoresizingMaskIntoConstraints
set toNO
The second rule does not seem to apply to top-level views for which you do not define constraints for. (Ex. the content view)
When looking at a Storyboard cell, notice that the cell does not have its contentView
exposed. We are not "controlling" the contentView
, Apple is.
Deep dive into storyboard source code and see how contentView
cell is defined:
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
Now the cell's subviews (notice the translatesAutoresizingMaskIntoConstraints="NO"
):
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="NaT-qJ-npL" userLabel="myCustomLabel">
The contentView
does not have it's translatesAutoresizingMaskIntoConstraints
set to NO
. Plus it lacks layout definition, maybe because of what @ecotax said.
If we look into the contentView
, it does have an autoresizing mask, but no definition for it: <autoresizingMask key="autoresizingMask"/>
So there are two conclusions:
contentView
translatesAutoresizingMaskIntoConstraints
is set toYES
.contentView
lacks definition of a layout.
This leads us to two solutions which have been talked about.
You can set the autoresizing masks manually in awakeFromNib
:
self.contentView.frame = cell.bounds;
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
Or you can set the contentView
translatesAutoresizingMaskIntoConstraints
to NO
in awakeFromNib
and define constraints in - (void)updateConstraints
.
This is the Swift version of @Igor's answer which is accepted and thanks for your nice answer mate.
First Goto your UICollectionViewCell
Subclass and paste the following code as it is inside the class.
override func awakeFromNib() {
super.awakeFromNib()
self.contentView.frame = self.bounds
self.contentView.autoresizingMask = [.FlexibleHeight, .FlexibleWidth]
}
By the way I am using Xcode 7.3.1 and Swift 2.3. Solution is tested on iOS 9.3 which is working flawlessly.
Thanks, Hope this helped.
In swift, place the following code in the collection view cell subclass:
override var bounds: CGRect {
didSet {
// Fix autolayout constraints broken in Xcode 6 GM + iOS 7.1
self.contentView.frame = bounds
}
}
contentView
iOS 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
}
이 메소드는 셀을 대기열에서 제거한 후에 호출해야합니다.
나는 이것을하고 고정했다 :
override func layoutSubviews() {
contentView.superview?.frame = bounds
super.layoutSubviews()
}
참조 : 여기
해당 콜렉션 뷰 셀의 펜촉에서 "하위 뷰 자동 크기 조정"확인란을 선택하십시오. iOS 8과 iOS 7 모두에서 잘 작동합니다.
'IT' 카테고리의 다른 글
IE에서 "테두리 반경"지원 (0) | 2020.06.04 |
---|---|
Twitter Bootstrap 3에서 col-lg-push 및 col-lg-pull을 사용한 열 순서 조작 (0) | 2020.06.04 |
클래스 접두사별로 CSS 선택기가 있습니까? (0) | 2020.06.04 |
앵귤러 2 호버 이벤트 (0) | 2020.06.04 |
Windows 7의 명령 프롬프트에서 Python 프로그램을 어떻게 실행합니까? (0) | 2020.06.04 |