Chris
Chris

Reputation: 2314

Swift - save ViewController set up after segue

At the Moment I have to ViewControllers. You can switch between ViewControllerA and ViewControllerB with show-segues. The problem is that every time I switch back, the ViewControllers state gets reseted. How can I save the setUp of a ViewController?

From A to B

    @IBAction func editButtonTapped(_ sender: Any) {
    let imageCollectionView = self.storyboard?.instantiateViewController(withIdentifier: "ImageCollectionVC") as! ImageCollectionViewController

    self.navigationController?.pushViewController(imageCollectionView, animated: true)
}

From B to A

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    tappedImage = images[indexPath.row]
    performSegue(withIdentifier: "backToPopUpView", sender: self)

}

Upvotes: 1

Views: 433

Answers (2)

flanker
flanker

Reputation: 4210

To move between view controllers passing data both ways you need a few things

  • a consistent method of navigation: segues or pushing/popping via a navigation controller or modally presenting/dismissing, but not a mix of them for one A - B - A transition

  • protocols/deleagtes to allow data to be passed back from th child to the parent.

In the example below navigation is via the navigation controller, and an image is used as an example of how to pass data back to the parent. It should be trivial to adapt this for other circumstances.

The child class needs an agreed interface with its parent to allow it to communicate. This is done with a protocol. In this example we provide a means for the child to pass its updated image back to the parent:

protocol ClassBDelegate {
    func childVCDidComplete(with image: UIImage?)
}

Then create a delegate variable in the child class that can point to any class that adopts the protocol (which in this case will be its parent) and then use that delegate and the protocol's function to pass the image data back. Once the data has been passed back via the delegate, view controller B calls the navigation controller's popViewCntroller method to close itself and return focus to view controller A

class B: UIViewController {
    var delegate: ClassBDelegate?

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        tappedImage = images[indexPath.row]
        delegate?.childVCDidComplete(with: tappedImage)
        navigationController?.popViewController(animated: true)
    }
}

For this all to work, the child view controller's delegate needs to be set to point its parent view controller (A), but before this can happen that class needs to conform to the protocol:

extension A: ClassBDelegate {}
    func childVCDidComplete( with image: UIImage?) {
        self.image = image
    }
}

Now, when instantiating the child view controller the parents set itself as the delegate, thus completing the communication loop.

Class A: UIViewController {
    var image: UIImage?

    @IBAction func editButtonTapped(_ sender: Any) {
        let imageCollectionView = self.storyboard?.instantiateViewController(withIdentifier: "ImageCollectionVC") as! ImageCollectionViewController
        imageCollectionView.delegate = self
        self.navigationController?.pushViewController(imageCollectionView, animated: true)
    }
}

Upvotes: 1

KNK
KNK

Reputation: 59

You are created new ViewControllerA, and you have the following result A -> B -> A. But it is not true, you should dismiss ViewControllerB...

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    tappedImage = images[indexPath.row]
    self.dismiss(animated: true, completion: nil)
    //performSegue(withIdentifier: "backToPopUpView", sender: self)

}

Upvotes: 0

Related Questions