[英]Swift4 - I can not show the CollectionView the first time "Unable to simultaneously satisfy constraints"
I am creating an app with Swift 4, where I make a request to the API and I want to return a result on a CollectionView.我正在使用 Swift 4 创建一个应用程序,在那里我向 API 发出请求,并且我想在 CollectionView 上返回结果。
But I get the following error, which I think is from constraints:但是我收到以下错误,我认为这是来自约束:
This block is repeated 100 times.此块重复 100 次。
And the result is that he does not paint any cells.结果是他没有画任何细胞。 Showing an image like this:
显示这样的图像:
Unless I press the top button "CHANGE AUTOLAYOUT" twice.除非我按两次顶部按钮“更改自动布局”。 Which is when you paint the cells of the two display modes you have, and it looks like this:
这是当您绘制您拥有的两种显示模式的单元格时,它看起来像这样:
And this:和这个:
But the problem is, initially nothing is shown and should be shown.但问题是,最初没有显示任何内容,应该显示。 And the error that I show you in the beginning appears.
我在开始时向您展示的错误出现了。
To help you a little, because I would say that the problem derives from the constrainst applied, I attach some images with the different constrainsts applied.为了帮助您,因为我会说问题源于应用的约束,所以我附上了一些应用了不同约束的图像。
The initial xib, where the collectionView is, are: collectionView 所在的初始 xib 是:
The cell that is initially loaded is:最初加载的单元格是:
The cell once we have changed the layout is this:我们更改布局后的单元格是这样的:
I attached the code of the main class, the ViewVontroller that controls the CollectionView:我附上了主类的代码,即控制 CollectionView 的 ViewVontroller:
import UIKit
import RxSwift
import RxCocoa
final class SpeedRunListViewController: UIViewController {
@IBOutlet private var collectionView: UICollectionView!
@IBOutlet private var buttonChangeLayout: UIButton!
private let disposeBag = DisposeBag()
private var viewModelList: SpeedRunListViewModel?
private var numElementsByCol: CGFloat = 3
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.isNavigationBarHidden = true
setupCollectionView()
viewModelList = SpeedRunListViewModel(interactor: InteractorSpeedRunSearch())
setupRx(viewModel: viewModelList!)
viewModelList?.fetch()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.isNavigationBarHidden = true
}
private func setupCollectionView() {
registerCollectionCells()
if #available(iOS 10.0, *) {
collectionView.isPrefetchingEnabled = false
} else {
// Fallback on earlier versions
}
calculateLayoutCollectionItem()
}
private func registerCollectionCells() {
collectionView.register(UINib(nibName: SpeedRunRowCollectionViewCell.nibName, bundle: nil),
forCellWithReuseIdentifier: SpeedRunRowCollectionViewCell.reuseCellId)
collectionView.register(UINib(nibName: SpeedRunCollectionViewCell.nibName, bundle: nil),
forCellWithReuseIdentifier: SpeedRunCollectionViewCell.reuseCellId)
}
private func calculateLayoutCollectionItem() {
if let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
layout.estimatedItemSize = CGSize.init(width: 2, height: 2)
}
}
private func setupRx(viewModel: SpeedRunListViewModel) {
viewModel.numElements.asObservable().subscribe(onNext: { e in
self.collectionView.reloadData()
}, onError: { error in
}, onCompleted: {
}, onDisposed: {
}).disposed(by: disposeBag)
buttonChangeLayout.rx.tap.subscribe(onNext: { void in
guard let value = self.viewModelList?.layoutRow else {
return
}
self.viewModelList?.layoutRow = !value
self.collectionView.collectionViewLayout.invalidateLayout()
self.collectionView.reloadData()
}, onError: { error in
}, onCompleted: {
}, onDisposed: {
}).disposed(by: disposeBag)
}
fileprivate func getCellId() -> String {
if let layoutRow = self.viewModelList?.layoutRow, layoutRow == true {
return SpeedRunRowCollectionViewCell.reuseCellId
}
return SpeedRunCollectionViewCell.reuseCellId
}
}
//MARK: - UICollectionViewDelegate, UICollectionViewDataSource
extension SpeedRunListViewController: UICollectionViewDelegate,
UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
guard let numElements = viewModelList?.numElements else {
return 0
}
return numElements.value
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: getCellId(), for: indexPath) as! SpeedRunCollectionViewCellBase
if let cellViewModel = viewModelList?.getCellViewModel(index: indexPath.row) {
cell.setupCell(viewModel: cellViewModel)
}
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard let speedRun = viewModelList?.getSpeedRun(index: indexPath.row) else {
return
}
let interactorDetail: InteractorSpeedRunDetail = InteractorSpeedRunDetail(speedRun: speedRun)
let viewControllerDetail: SpeedRunDetailViewController = SpeedRunDetailViewController(interactor: interactorDetail)
viewControllerDetail.URISpeedRunDetail = (speedRun.links![1].uri)!
navigationController?.pushViewController(viewControllerDetail, animated: true)
}
}
And the truth is that I do not know why that conflict of layouts occurs.事实是,我不知道为什么会发生布局冲突。 But it's driving me crazy ... I can not understand how the cells are not shown initially (because data is being received).
但它让我发疯......我无法理解最初如何不显示单元格(因为正在接收数据)。 What could it be?
会是什么呢?
Thank you very much, any question you attach it to me.非常感谢,有什么问题可以发给我。
[CODE UPDATED] [代码更新]
These is the code solution:这些是代码解决方案:
//MARK: - UICollectionViewDelegateFlowLayout
extension SpeedRunListViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize{
if let value = self.viewModelList?.layoutRow {
if value {
return CGSize(width: 320, height: 144)
}
else{
return CGSize(width: 96, height: 162)
}
}
return CGSize(width: 320, height: 144)
}
}
You are not setting the UICollectionViewDelegateFlowLayout in the viewController.您没有在 viewController 中设置 UICollectionViewDelegateFlowLayout。 You need to set it and then use
您需要设置它然后使用
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize
To set the sizes of your cells.设置单元格的大小。
You are having the error because when you load the cells the very first time you are basically telling them that they have a size of 0 0.您遇到错误是因为当您第一次加载单元格时,您基本上是在告诉他们它们的大小为 0 0。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.