UICollectionViewController
を使用するUICollectionViewFlowLayout
があります。ここで、itemSize
はUICollectionView
のサイズです。基本的に、これは各セルがフルスクリーンで水平にスクロールするセルの行レイアウトです。
UICollectionViewFlowLayout
サブクラスでは、prepareLayout
を次のようにオーバーライドしました。
- (void)prepareLayout {
self.itemSize = self.collectionView.frame.size;
self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
self.collectionView.pagingEnabled = YES;
self.minimumLineSpacing = 0.0;
self.minimumInteritemSpacing = 0.0;
self.sectionInset = UIEdgeInsetsZero;
self.footerReferenceSize = CGSizeZero;
self.headerReferenceSize = CGSizeZero;
}
UICollectionViewController
は、1つのセクションで10個のアイテムを返す非常に基本的なものです。詳細については、 GitHubのサンプルプロジェクト を含めました。
すべてが正しくセットアップされているようです。シミュレーターとデバイスでは正しく表示されますが、コレクションビューが表示されると、コンソールにエラーが記録されます。
the behavior of the UICollectionViewFlowLayout is not defined because: the item height must be less that the height of the UICollectionView minus the section insets top and bottom values.
また、私の例のコレクションビューコントローラーはNavigation Controllerにあり、この例では特に必要ないように見えますが、実際のケースではコレクションビューコントローラーが必要ですナビゲーションコントローラー
UIViewController
–_automaticallyAdjustsScrollViewInsets
–には、デフォルトでYES
に設定されているプロパティがあります。これは、UIViewController
のビュー階層にUIScrollView
がある場合(UICollectionViewController
に当てはまる場合)、そのスクロールビューのcontentInset
プロパティが調整されることを意味します。ステータスバー、ナビゲーションバー、ツールバー、またはタブバーによって消費される画面領域を自動的に考慮します。
そのプロパティのドキュメントには次のように記載されています。
AdjustsScrollViewInsets
View Controllerがスクロールビューのインセットを自動的に調整するかどうかを指定します。
@property(nonatomic, assign) BOOL automaticallyAdjustsScrollViewInsets
ディスカッション
デフォルト値はYESです。これにより、ステータスバー、ナビゲーションバー、ツールバーまたはタブバーによって消費される画面領域に応じて、View Controllerがスクロールビューのインセットを調整できます。ビュー階層に複数のスクロールビューがある場合など、スクロールビューのインセット調整を自分で管理する場合は、NOに設定します。
解決策は、automaticallyAdjustsScrollViewInsets
のように、NO
サブクラスのどこかにUICollectionViewController
をviewDidLoad
に設定することです。
- (void)viewDidLoad {
[super viewDidLoad];
self.automaticallyAdjustsScrollViewInsets = NO;
}
GitHubのサンプルプロジェクト を追加しました。これはこの問題と解決策を示しています。 2つのブランチがあります:with_error
およびfixed_error
。 GitHubの変更の差分 です。
この問題は、3x画面(つまりiPhone 6 Plus)で発生しました。判明したように、自動レイアウトエンジンは無限浮動小数点値(.33333333など)を好まなかったため、私の解決策はfloor
でした。 sizeForItemAt:indexPath:
の戻り高さ。
return CGSize(width: preferredWidth, height: floor(preferredHeight))
iOS 11アップデート:automaticallyAdjustsScrollViewInsets
はiOS 11.0で廃止されました。
アップルでは、代わりにUIScrollView
のcontentInsetAdjustmentBehavior
メソッドを使用することをお勧めします。この値を.never
に設定すると、エラーがなくなりました。 Interface Builderでこのプロパティを設定することもできます。
デバイスをポートレートからランドスケープに、ポートレートに戻すときにこの問題が発生しました。次のように、デバイスの回転時およびsuperの呼び出し前にcollectionView
のレイアウトを無効化します。
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
// Causes collection view cells to be resized upon orientation change.
// Important that this is called *before* call to super in order to prevent error from being logged to console.
[self.collectionView.collectionViewLayout invalidateLayout];
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
//...
}
iOS 10:一番上のビューがビューアウトレットに接続されていません
同様の問題がありました。
スクリーンの全幅と高さのロードセルの後。いくつかの条件でセルの高さを変更すると、同じエラーが発生しました
これを修正する
私は使った
func updateHeightPerRatio(with image:UIImage) {
let ratio = collectionView.bounds.width / image.size.width
constHeightCollectionView .constant = ceil(image.size.height * ratio)
collectionView.reloadData()
collectionView.performBatchUpdates({
collectionView.layoutIfNeeded()
}) { (completed) in
self.collectionView.reloadData()
self.layoutIfNeeded()
}
}
解決策は、データをリロードし、そのコレクションビューでバッチ更新を実行してフレームを再計算することです。コレクションビューを再度リロードした後、計算されたフレームをセルに適用します
そして今、問題のログはありません。
お役に立てば幸いです