Xcode 6 Beta 3、iOS 8 SDKを使用しています。 Swiftを使用してTarget iOS 7.0をビルドします。以下のスクリーンショットを使用して、問題をステップごとに参照してください。
StoryboardにUICollectionViewがあります。 1プロトタイプUICollectionViewCellには、中央に1つのラベルが含まれます(自動サイズ変更ルールはありません)。紫色の背景は、セルによって実行時に生成されるcontentViewをマークすることでした。そのビューは、最終的にはUICollectionViewLayoutDelegateに基づいて適切にサイズ変更されますが、iOS 7ではありません。Xcode6を使用しているため、問題はiOS 7でのみ発生します。
IOS 8でアプリを作成するとき、すべては大丈夫です。
注:紫色はcontentView、青色は角の丸いUIButtonです
ただし、iOS 7では、セル内のすべてのサブビューが(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;
}
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の使用が自動的に開始されるため、ユーザーに打撃を与えます。
前にコメントしたように、回避策のダニエル・プラマンが作品を説明してくれました。しかし、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では、iOS7デバイスのUICollectionViewCellのcontentViewが壊れています。また、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に関連していると言うことはできませんが、ランタイムとは関係ありませんが、私は非常に自信があります。
この質問を読んだ人全員がAppleにレーダーを提出することを願っています。これは大きな問題であり、最終的なXcodeリリースの前に対処する必要があります。
編集: ecotaxの投稿 に照らして、これを更新して、iOS 8とiOS 7のビルドの動作の違いが確認されたが、バグではないことを伝えました。この問題を修正したのは、iOS 7でビルドすると、この機能を実現するために必要なコンテンツビューに自動サイズ変更マスクが追加され、Appleが追加されなくなったためです。
これは、@ 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でテストされています。
ありがとう、これが役に立てば幸いです。
この投稿での答えは、私が理解したことはありませんwhy.
まず、2つの「ルール」があります。
[UIView new]
)の場合、プロパティtranslatesAutoresizingMaskIntoConstraints
はYES
に設定されますtranslatesAutoresizingMaskIntoConstraints
がNO
に設定されます。2番目のルールは、制約を定義していないトップレベルビューには適用されないようです。 (例:コンテンツビュー)
Storyboardセルを見ると、セルのcontentView
が公開されていないことに注意してください。 contentView
、Appleは「制御」していません。
ストーリーボードのソースコードを詳しく見て、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
には、translatesAutoresizingMaskIntoConstraints
がNO
に設定されていません。さらに、おそらく @ ecotax said が原因で、レイアウト定義が不足しています。
contentView
を調べると、自動サイズ変更マスクがありますが、定義はありません:<autoresizingMask key="autoresizingMask"/>
したがって、2つの結論があります。
contentView
translatesAutoresizingMaskIntoConstraints
はYES
に設定されます。contentView
にはレイアウトの定義がありません。これは、私たちが話し合ってきた2つの解決策につながります。
awakeFromNib
で自動サイズ変更マスクを手動で設定できます。
self.contentView.frame = cell.bounds;
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
または、contentView
でtranslatesAutoresizingMaskIntoConstraints
NO
をawakeFromNib
に設定し、- (void)updateConstraints
で制約を定義できます。
Swiftで、コレクションビューのセルサブクラスに次のコードを配置します。
override var bounds: CGRect {
didSet {
// Fix autolayout constraints broken in Xcode 6 GM + iOS 7.1
self.contentView.frame = bounds
}
}
IOS 8ではcontentView
のサイジングにも問題があることがわかりました。これは、サイクルの非常に遅くにレイアウトされる傾向があり、一時的な制約の競合を引き起こす可能性があります。これを解決するために、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()
}
参照: ここ