When I add an image from the TattooIdeas screen to a collection in the FavoriteTattooIdeas screen, the application crashes with the error "UICollectionView must be initialized with a non-null layout parameter".
class TattooIdeasViewController: UIViewController { // some code
//I think the error is in this part of the code.
''' @objc private func addBarButtonTapped(){
let selectedPhotos = collectionView.indexPathsForSelectedItems?.reduce([], { (photosss, indexPath) -> [Result] in
var mutablePhotos = photosss
let photo = photos[indexPath.item]
mutablePhotos.append(photo)
return mutablePhotos
})
let alertController = UIAlertController(title: "", message: "\(selectedPhotos!.count) фото будут добавлены в альбом", preferredStyle: .alert)
let add = UIAlertAction(title: "Добавить", style: .default) { (action) in
let favVC = FavouritesTattooIdeaController()
favVC.photos.append(contentsOf: selectedPhotos ?? [])
favVC.collectionView.reloadData()
self.refresh()
}
let cancel = UIAlertAction(title: "Отменить", style: .cancel) { (action) in
}
alertController.addAction(add)
alertController.addAction(cancel)
present(alertController, animated: true)
}
'''
if I declare let favVC = FavoritesTattooIdeaController(collectionViewLayout: UICollectionViewFlowLayout()), then the application does not crash, but the pictures are not displayed in the collectionView on the FavoriteTattooIdeas screen.
class FavouritesTattooIdeaController: UICollectionViewController {
var photos = [Result]()
private let enterSearchTermLabel: UILabel = {
let label = UILabel()
label.text = "You haven't add a photos yet"
label.textAlignment = .center
label.font = UIFont.boldSystemFont(ofSize: 20)
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
override func viewDidLoad() {
super.viewDidLoad()
collectionView.backgroundColor = .white
collectionView.register(FavouritesTattooIdeaCell.self, forCellWithReuseIdentifier: FavouritesTattooIdeaCell.reuseId)
collectionView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
layout.minimumInteritemSpacing = 1
layout.minimumLineSpacing = 1
setupEnterLabel()
}
private func setupEnterLabel() {
collectionView.addSubview(enterSearchTermLabel)
enterSearchTermLabel.centerXAnchor.constraint(equalTo: collectionView.centerXAnchor).isActive = true
enterSearchTermLabel.topAnchor.constraint(equalTo: collectionView.topAnchor, constant: 50).isActive = true
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
enterSearchTermLabel.isHidden = photos.count != 0
return photos.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: FavouritesTattooIdeaCell.reuseId, for: indexPath) as! FavouritesTattooIdeaCell
let googlePhoto = photos[indexPath.item]
cell.googlePhoto = googlePhoto
return cell
}
}
// MARK: - UICollectionViewDelegateFlowLayout
extension FavouritesTattooIdeaController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = collectionView.frame.width
return CGSize(width: width/3 - 1, height: width/3 - 1)
}
}
You are missing the fact that
FavouritesTattooIdeaController()is short forFavouritesTattooIdeaController.init(). So here, you are creating a new object. Same forFavouritesTattooIdeaController(collectionViewLayout:)andFavouritesTattooIdeaController.init(collectionViewLayout:).What's happening:
You are in your
UIAlertActioncreating a new object ofFavouritesTattooIdeaController. Then, later you are creating a newFavouritesTattooIdeaControllerto show it. But they aren't related to each other.Imagine that a
init()is like getting a new empty box.So you create a new box, put your favorites photos, andd since you don't use it, you just discard it afterwards. Then, when you want to display your favorites, you create again a new empty box, and expect to have the previous items put inside the other box. See the issue?
To solve the issue:
You need to keep inside
TattooIdeasViewControlleran array ofselectedPhotos. And put it toFavouritesTattooIdeaControllerwhen you'll show it.OR
Use the same variable
FavouritesTattooIdeaController(be it a property ofTattooIdeasViewController), so you add each time the photos, and it will keep all of thems.