-1

I got a HomeController of type UICollectionViewController which handles some PictureCells (contains a picture and a label). Now I am sending one PictureCell to another ViewController to edit the label. This all works perfectly. I could send it back to the HVC using a protocol but instead of going back I want to go one step further and Display the edited PictureCell in a new ViewController.

Instead of creating a completely new one, I am subclassing the existing HomeController to reuse his CollectionView. All works fine and the view shows up but the edited PictureCell is not showing up at all, even tho I can show it's layer, the Cell itself with its content doesn't show up.

(Messy) Class-Diagram looks like this: ClassDiagram

    class HomeController: UICollectionViewController, UICollectionViewDelegateFlowLayout, MyProtocol {


    override func viewDidLoad() {
        super.viewDidLoad()

        collectionView?.backgroundColor = UIColor.black
        collectionView?.register(PictureCell.self, forCellWithReuseIdentifier: Constants.cellId)
    }


    //MARK: Get value from second VC
    var valueSentFromSecondViewController: String?
    var cellSentFromSecondViewController: PictureCell?

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(true)
        //Acting with Protocol here
    }
     //HERE ARE THE COLLECTIONVIEWFUNCTIONS
}


class PictureEditViewController: UIViewController, UITextFieldDelegate {

    var delegate:MyProtocol?
    var myCell: PictureCell?

    let collectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
        cv.backgroundColor = UIColor.white
        return cv
    }()

    init(pictureCellInit: PictureCell?) {
        self.myCell = pictureCellInit
        super.init(nibName: nil, bundle: nil)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        showThings()
    }

    @objc func showNextVC() {
        let newViewController = PictureShowViewController(withCell: self.myCell)
        newViewController.modalPresentationStyle = .overCurrentContext
        present(newViewController, animated: true) //with dismiss
    }


    @objc func showThings() {
        view.addSubview(collectionView)
        self.collectionView.frame = CGRect(x: x, y: y, width: width, height: height)
        self.setupViews()
    }

    func setupViews() {
        //ADDING THE SUBVIEWS
    }

    func confBounds() {
        //LAYOUT
    }

    @objc func handleDismiss() {
        self.dismiss(animated: true, completion: nil)
    }


class PictureShowViewController: HomeController {

    //MARK: Variable/Constant declaration
    var myCellToShow: PictureCell?

    init(withCell: PictureCell?) {
        let layoutUsing = UICollectionViewFlowLayout()
        myCellToShow = withCell
        super.init(collectionViewLayout: layoutUsing)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        collectionView?.backgroundColor = .white
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(true)
        collectionView?.addSubview(myCellToShow!)
        self.collectionView?.reloadData()
    }

    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 1
    }


    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        if let cell = myCellToShow {
            cell.layer.borderColor = UIColor.red.cgColor
            cell.layer.borderWidth = 2
            return cell
        }
        else {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: Constants.cellId, for: indexPath) as! PictureCell
            return cell
        }
    }

    //Size of Cell
    override func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

        let cellSize = CGFloat(view.frame.width)
        return CGSize(width: cellSize, height: cellSize)
    }
}

Does anyone have an idea where I went wrong?

Noodledew
  • 509
  • 4
  • 19

1 Answers1

1

It is a bad idea to use PictureCell to move your data around view controllers. UICollectionView reuses instances of cells so the content of the cell is bound to change anytime.

So instead of using your cell, hand over the underlying data and insert the data in to the newly dequeued collection view cell.

In the end, var cellSentFromSecondViewController: PictureCell? should be var pictureFromSecondViewController: YourPictureData

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: Constants.cellId, for: indexPath) as! PictureCell

    //Set your data
    cell.picture = pictureFromSecondViewController

    return cell
}
sj-r
  • 561
  • 2
  • 10
  • I did it like this in the first place but a very experienced guy of my company told me to not do it that way and that the better approach is to just pass around the instance of the Cell I want to edit. – Noodledew Aug 16 '18 at 07:33
  • 1
    Well, I think the nature of cells being reused by the collection view makes it unsuitable to store it somewhere and expect it to be what you think it would be later in the future. I just think of cells as a disposable plate to put my food(data) on, and the food can be replaced anytime. – sj-r Aug 16 '18 at 08:48
  • But you could also give around a plate and your friends modify the food on it.. ;) – Noodledew Aug 16 '18 at 09:14
  • @sj-r is right. The Collection View has control over its own cells. It decides when to reuse cells. So if you try to use a cell somewhere else, the old collection view still owns it and can try to reuse it whenever it wants to. – ABeard89 Aug 16 '18 at 13:01
  • @Noodledew yea.. the problem is that you want the banana you placed five minutes ago but your friend replaced it with strawberries and you have no way to get back the banana you wanted. :( – sj-r Aug 16 '18 at 14:21