简体   繁体   中英

Swift: How to reuse a ViewController properly

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?

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
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM