ios 为什么当单元格全屏时 UICollectionView 会记录错误?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23596181/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why does UICollectionView log an error when the cells are fullscreen?
提问by Wes
I have a UICollectionViewController
using a UICollectionViewFlowLayout
where my itemSize
is the size of the UICollectionView
. Basically, this is a line layout of cells where each cell is fullscreen and scrolls horizontally.
我有一个UICollectionViewController
using a UICollectionViewFlowLayout
,其中 myitemSize
是UICollectionView
. 基本上,这是一个单元格的行布局,其中每个单元格都是全屏的并水平滚动。
In my UICollectionViewFlowLayout
subclass, I have overridden prepareLayout
as follows:
在我的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;
}
The UICollectionViewController
is very basic returning 10 items in one section. I've included a sample project on GitHubfor more detail.
这UICollectionViewController
是非常基本的一个部分返回 10 个项目。我在 GitHub 上包含了一个示例项目以获取更多详细信息。
Everything appears to be set up correctly. It looks right in the simulator and on the device but, when the collection view is displayed, there is an error logged to the console:
一切似乎都设置正确。它在模拟器和设备上看起来都不错,但是当显示集合视图时,控制台会记录一个错误:
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.
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.
Note also that the collection view controller in my example is in a navigation controller and while that doesn't look particularly necessary in the example, in my real-world case I need the collection view in a navigation controller.
另请注意,我的示例中的集合视图控制器位于导航控制器中,虽然在示例中看起来不是特别必要,但在我的实际情况中,我需要导航控制器中的集合视图。
回答by Wes
There is a property on UIViewController
–automaticallyAdjustsScrollViewInsets
–that defaults to YES
. This means that when a UIViewController
has a UIScrollView
in its view hierarchy–which is true of a UICollectionViewController
–the contentInset
property of that scroll view is adjusted automatically to account for screen areas consumed by the status bar, navigation bar, and toolbar or tab bar.
UIViewController
– automaticallyAdjustsScrollViewInsets
–上有一个属性,默认为YES
。这意味着当 a在它的视图层次结构中UIViewController
有 aUIScrollView
时——这对 a 来说是真的UICollectionViewController
——contentInset
滚动视图的属性会自动调整以考虑状态栏、导航栏和工具栏或标签栏消耗的屏幕区域。
The documentation for that property states:
该属性的文档说明:
automaticallyAdjustsScrollViewInsets
Specifies whether or not the view controller should automatically adjust its scroll view insets.
@property(nonatomic, assign) BOOL automaticallyAdjustsScrollViewInsets
Discussion
Default value is YES, which allows the view controller to adjust its scroll view insets in response to the screen areas consumed by the status bar, navigation bar, and toolbar or tab bar. Set to NO if you want to manage scroll view inset adjustments yourself, such as when there is more than one scroll view in the view hierarchy.
自动调整ScrollViewInsets
指定视图控制器是否应自动调整其滚动视图插入。
@property(nonatomic, assign) BOOL automaticallyAdjustsScrollViewInsets
讨论
默认值为 YES,它允许视图控制器根据状态栏、导航栏和工具栏或选项卡栏消耗的屏幕区域调整其滚动视图插入。如果您想自己管理滚动视图插入调整,请设置为 NO,例如当视图层次结构中有多个滚动视图时。
The solution is to set automaticallyAdjustsScrollViewInsets
to NO
somewhere in your UICollectionViewController
subclass, such as in viewDidLoad
:
解决方案是设置automaticallyAdjustsScrollViewInsets
到子类中的NO
某个位置UICollectionViewController
,例如在viewDidLoad
:
- (void)viewDidLoad {
[super viewDidLoad];
self.automaticallyAdjustsScrollViewInsets = NO;
}
I have put an example project on GitHubthat illustrates this problem and solution. There are two branches: with_error
and fixed_error
. Here is a diff of the change on GitHub.
我在 GitHub 上放了一个示例项目来说明这个问题和解决方案。有两个分支:with_error
和fixed_error
。这是GitHub 上更改的差异。
回答by Legonaftik
iOS 11 update:automaticallyAdjustsScrollViewInsets
is deprecated in iOS 11.0.
iOS 11 更新:automaticallyAdjustsScrollViewInsets
在 iOS 11.0 中已弃用。
Apple recommends using UIScrollView
's contentInsetAdjustmentBehavior
method instead. I set this value to .never
and the error has gone. You can also set this property in Interface Builder.
Apple 建议改用UIScrollView
的contentInsetAdjustmentBehavior
方法。我将此值设置为.never
并且错误消失了。您也可以在 Interface Builder 中设置此属性。
回答by Tamás Sengel
This issue just occured to me on 3x screens (namely the iPhone 6 Plus.) As it turned out, the autolayout engine did not really like infinite floating point values (such as .33333333), so my solution was to floor
the return height in sizeForItemAt:indexPath:
.
这个问题只是在 3x 屏幕(即 iPhone 6 Plus)上发生在我身上。事实证明,自动布局引擎并不真正喜欢无限浮点值(例如 .33333333),所以我的解决方案是 .33333333 中floor
的返回高度sizeForItemAt:indexPath:
。
return CGSize(width: preferredWidth, height: floor(preferredHeight))
回答by Stunner
I encountered this problem when rotating the device from portrait to landscape, back to portrait. You want to invalidate the collectionView
's layout upon device rotation and before the call to super, like so:
我在将设备从纵向旋转到横向,再旋转回纵向时遇到了这个问题。您希望collectionView
在设备旋转时和调用 super 之前使 的布局无效,如下所示:
- (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];
//...
}
回答by Hardy_Germany
Like Stunner, I had the same problem when rotating from landscape (picture using full width) to portrait mode. His suggestion was the only one which really helped.
像 Stunner 一样,从横向(使用全宽的图片)旋转到纵向模式时,我遇到了同样的问题。他的建议是唯一真正有帮助的建议。
Attached the code with latest Swift for his ObjC example ... and as a bonus, my code to find the center cell of the collection view. Works quite nice ;-)
为他的 ObjC 示例附加了最新的 Swift 代码......作为奖励,我的代码用于查找集合视图的中心单元格。效果很好;-)
/**
-----------------------------------------------------------------------------------------------
viewWillTransition()
-----------------------------------------------------------------------------------------------
*/
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
// find cell in the center of the screen and store it in a global variable
let center = self.view.convert((self.collectionView!.center), to: self.collectionView)
// get the indexPath for the cell in the center of the current screen
if let index = collectionView!.indexPathForItem(at: center) {
// store it in a class property
self.indexPathOfCenterCell = index
}
// force recalculation of margins, borders, cell sizes etc.
self.collectionView?.collectionViewLayout.invalidateLayout()
// inform UIKit about it
super.viewWillTransition(to: size, with: coordinator)
}
回答by Nithyashree
This way had worked for me perfectly!.
这种方式对我来说非常有效!
I just subtracted the top and bottom insets from the view's height as said in that error.
如该错误所述,我只是从视图的高度中减去了顶部和底部的插图。
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: view.frame.width , height: view.frame.height - (view.safeAreaInsets.top + view.safeAreaInsets.bottom))
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: view.frame.width , height: view.frame.height - (view.safeAreaInsets.top + view.safeAreaInsets.bottom))
}
I hope it helps!
我希望它有帮助!
回答by Anton Tropashko
ios 10: topmost view was not connected to the view outlet
ios 10:最上面的视图没有连接到视图插座
回答by Prashant Tukadiya
I had similar issue.
我有类似的问题。
After load cell which is full width and some height of screen. on some condition I changed the height of cell then I was getting the same error
在全宽和一些屏幕高度的称重传感器之后。在某些情况下,我改变了单元格的高度,然后我得到了同样的错误
to fix this
解决这个问题
I used
我用了
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()
}
}
Solution is reload data then perform batchupdate with that collection view re -calculate the frames . after that reload collectionview again it will apply calculated frames to cell
解决方案是重新加载数据,然后使用该集合视图执行批量更新,重新计算帧。再次重新加载 collectionview 后,它会将计算出的帧应用于单元格
And now there is no log for issue now.
现在没有问题日志。
Hope it is helpful
希望它有帮助
回答by Lenda
I was getting the same error when I was trying to embed a UICollectionView
in a UITableView
. I was generating a new UICollectionView
in each UITableView
cell, but I did not put any constraints on the height of that UICollectionView
. So, when I put a constraint on the height, that error is gone!
当我尝试将 a 嵌入UICollectionView
到UITableView
. 我UICollectionView
在每个UITableView
单元格中生成一个新的,但我没有对那个UICollectionView
. 所以,当我对高度施加限制时,这个错误就消失了!
回答by Ammar Mujeeb
In my case I have to reduce bottom inset (from 20 to 0) of cell as I have reduced 20 from height of collectionview From
在我的情况下,我必须减少单元格的底部插入(从 20 到 0),因为我从 collectionview 的高度减少了 20
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
- return UIEdgeInsets(top: 10, left: 10, bottom: 20, right: 10)
+ return UIEdgeInsets(top: 10, left: 10, bottom: 0, right: 10)
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
let size = CGSize(width: 350, height: collectionView.bounds.size.height - 20)
return size
}