I have built a form where the user can write down his report. When I click on a textField the keyboard appears and the view is messed up and I can't figure out why it's happening. I also get this error message a bunch of times. Some informations of how I have built the view. The cells of this collectionsView are also collectionViews which show the view that is displayed (the part with the white background color). The light blue color (bottom) at the end of the gif is the background color of the homeContoller collectionView. The buttonContainer is a part of the newReportCell object which is a cell inside the homeController collectionView. It would be really helpful if someone has an idea of how to fix this bug.
2018-08-21 14:28:53.772211+0200 TestApp[91209:4755287] The behavior of the UICollectionViewFlowLayout is not defined because: 2018-08-21 14:28:53.772389+0200 TestApp[91209:4755287] the item height must be less than the height of the UICollectionView minus the section insets top and bottom values, minus the content insets top and bottom values. 2018-08-21 14:28:53.772610+0200 TestApp[91209:4755287] The relevant UICollectionViewFlowLayout instance is , and it is attached to ; layer = ; contentOffset: {768, 0}; contentSize: {1536, 858}; adjustedContentInset: {0, 0, 263, 0}> collection view layout: . 2018-08-21 14:28:53.772728+0200 TestApp[91209:4755287] Make a symbolic breakpoint at UICollectionViewFlowLayoutBreakForInvalidSizes to catch this in the debugger.
import UIKit
class HomeController: UICollectionViewController, UICollectionViewDelegateFlowLayout{
let cellId = "cellId"
let cellId2 = "cellId2"
let appTitles = ["Test" , "TestView"]
var currentIndexPath = IndexPath(item: 0, section: 0)
lazy var menuBar: MenuBar = {
let mb = MenuBar()
mb.homeController = self
mb.translatesAutoresizingMaskIntoConstraints = false
return mb
}()
override func viewDidLoad() {
super.viewDidLoad()
initView()
}
func initView() {
navigationItem.title = "Test"
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Logout", style: .plain, target: self, action: #selector(handleLogout))
navigationController?.navigationBar.prefersLargeTitles = true
setupMenuBar()
setupCollectionView()
setupMenuButtons()
observeKeyboardNotifications()
}
func setupCollectionView() {
if let flowLayout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
flowLayout.scrollDirection = .horizontal
flowLayout.minimumLineSpacing = 0
}
// blue background color
collectionView?.backgroundColor = UIColor(r: 198, g: 225, b: 243)
collectionView?.register(FeedCell.self, forCellWithReuseIdentifier: cellId)
collectionView?.register(NewReportCell.self, forCellWithReuseIdentifier: cellId2)
collectionView?.translatesAutoresizingMaskIntoConstraints = false
collectionView?.topAnchor.constraint(equalTo: menuBar.bottomAnchor).isActive = true
collectionView?.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
collectionView?.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
collectionView?.heightAnchor.constraint(equalTo: view.heightAnchor, constant: -166).isActive = true
collectionView?.isPagingEnabled = true
}
func setupMenuButtons() {
let synchroImage = UIImage(named: "synchronize")
let synchroBarButtonItem = UIBarButtonItem(image: synchroImage, style: .plain, target: self, action: #selector(handleSync))
navigationItem.rightBarButtonItems = [synchroBarButtonItem]
}
private func setTitleForIndex(index: Int) {
navigationItem.title = appTitles[Int(index)]
dismissKeyboard()
}
@objc func dismissKeyboard() {
self.view.endEditing(true)
}
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
menuBar.horizontalBarLeadingAnchorConstraint?.constant = scrollView.contentOffset.x / CGFloat(appTitles.count)
}
override func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let index = targetContentOffset.pointee.x / view.frame.width
let indexPath = IndexPath(item: Int(index), section: 0)
currentIndexPath = indexPath
menuBar.collectionView.selectItem(at: indexPath, animated: true, scrollPosition: [])
setTitleForIndex(index: Int(index))
self.invalidateLayoutForCell(index: Int(index))
}
func invalidateLayoutForCell(index: Int) {
if index == 0 {
self.feedCell?.invalidateLayout()
} else {
self.newReportCell?.invalidateLayout()
}
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return appTitles.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.item == 0{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! FeedCell
cell.homeController = self
feedCell = cell
return cell
}
else {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId2, for: indexPath) as! NewReportCell
cell.homeController = self
newReportCell = cell
return cell
}
}
func pushViewController(controller: UICollectionViewController, animated: Bool) {
navigationController?.pushViewController(controller, animated: animated)
}
func scrollToMenuIndex(menuIndex: Int) {
let indexPath = IndexPath(item: menuIndex, section: 0)
currentIndexPath = indexPath
collectionView?.scrollToItem(at: indexPath, at: [], animated: true)
setTitleForIndex(index: menuIndex)
DispatchQueue.main.async {
}
}
func invalidateLayout() {
self.collectionView?.collectionViewLayout.invalidateLayout()
DispatchQueue.main.async {
self.collectionView?.scrollToItem(at: self.currentIndexPath, at: .centeredHorizontally, animated: true)
self.menuBar.refreshView()
self.feedCell?.invalidateLayout()
self.newReportCell?.invalidateLayout()
}
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
invalidateLayout()
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
print(collectionView.frame.width, " - " , collectionView.frame.height)
return CGSize(width: collectionView.frame.width, height: collectionView.frame.height)
}
private func setupMenuBar() {
view.addSubview(menuBar)
menuBar.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
menuBar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
menuBar.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
menuBar.heightAnchor.constraint(equalToConstant: 50).isActive = true
}
fileprivate func observeKeyboardNotifications() {
NotificationCenter.default.addObserver(self, selector: #selector(keyboardShow), name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardHide), name: .UIKeyboardWillHide, object: nil)
}
@objc func keyboardShow() {
if(UIDevice.current.orientation == UIDeviceOrientation.landscapeLeft || UIDevice.current.orientation == UIDeviceOrientation.landscapeRight){
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
self.view.frame = CGRect(x: 0, y: -150, width: self.view.frame.width, height: self.view.frame.height)
}, completion: nil)
}
else {
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
self.view.frame = CGRect(x: 0, y: -50, width: self.view.frame.width, height: self.view.frame.height)
}, completion: nil)
}
print("keyboard shown")
}
@objc func keyboardHide() {
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
self.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height)
}, completion: nil)
print("keyboard hide")
}
}