The app crashes when I try to add a picture to my favorites collection. Swift

47 Views Asked by At

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)
}

}

1

There are 1 best solutions below

0
Larme On

You are missing the fact that FavouritesTattooIdeaController() is short for FavouritesTattooIdeaController.init(). So here, you are creating a new object. Same for FavouritesTattooIdeaController(collectionViewLayout:) and FavouritesTattooIdeaController.init(collectionViewLayout:).

What's happening:

You are in your UIAlertAction creating a new object of FavouritesTattooIdeaController. Then, later you are creating a new FavouritesTattooIdeaController to 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 TattooIdeasViewController an array of selectedPhotos. And put it to FavouritesTattooIdeaController when you'll show it.

OR

Use the same variable FavouritesTattooIdeaController (be it a property of TattooIdeasViewController), so you add each time the photos, and it will keep all of thems.