简体   繁体   中英

How Pass Data back a view controller in the stack?

I've seen a lot of questions in this category but they all seem to be be answer in the same manner, which is simply passing data between viewcontrollers, which isnt what I think I'm looking for.

I have VC1 that has data stored in it, under particular circumstance the user needs to entire information in VC2. I need that info to be pass down the back to VC1, lets called the data "info"

I code I was hoping to use was like this. I access the VC stack and assign the variables to an optional "info" variable (given at compile time the stack doesn't know what the VC type is one down on the stack.

let nav = self.navigationController
let nextView = nav?.viewControllers[(nav?.viewControllers.count)! - 1]
****//code that isn't working
nextView.info = self.info => Value of type 'UIViewController?' has no member 'info'

****//This works fine
nav?.popViewController(animated: true)

You need to cast it

if let let nextView = nav?.viewControllers[(nav?.viewControllers.count)! - 1] as? VCName {
   nextView.info = self.info
}

It's fragile to assume that you're in a navigation stack and that the view controller one below you is the one you need to talk to.

My guess is that the previous view controller pushed you, and gave you the data you're editing.

It would be better/cleaner to set up a delegate protocol between the 2 view controllers, and make yourself the new view controller's delegate before pushing it. Then it would just send a message to it's delegate to pass the data back.

nextView is considered as it's superclass UIViewController because the array viewControllers from the UINavigationController is defined like so ( [UIViewController] ).

If your VC1 is of type FirstVC (subclass of UIViewController ), you should cast it to its actual class to be able to "see" your additional properties. The same with your next view controllers. So, what happens if you do this?

let nextView = nav?.viewControllers[(nav?.viewControllers.count)! - 1] as? SecondVC

Of course, assuming your nextView is of class SecondVC . Remember that object oriented programming has polymorphism , in which all your view controllers are descendants of UIViewController and, thus, they are a UIViewController in general and these situations can happen.

Anyway, the correct way would be to define a protocol, make FirstVC conform to it, pass the first view controller as a parameter to the SecondVC and, in the second view controller, call the protocol method back to the first view controller when choosing an option. Something like:

protocol PassDataBackProtocol {
    var result: String
}

class FirstVC: UIViewController, PassDataBackProtocol {
    var result: String = "" {
        didSet {
            // Update your view
        }
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let secondVC = segue.destination as? SecondVC {
            secondVC.firstVC = self
        }
    }
}

class SecondVC: UIViewController {
    weak var firstVC: PassDataBackProtocol?

    func didChangeValue(newValue: String) {
        firstVC?.result = newValue
        navigationController?.popViewController(animated: true)
    }
}

If you're using pushViewController(_:animated:) instead of segues, then set firstVC before doing the push.

EDIT: I added the weak property to the back pointer, since it's important to avoid retain cicles.

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