-3

I have a view controller, lets call it vc1, which passes some data to another (vc2) using prepare for segue, and then calling performSegue.

Is there a way to pass some data back from vc2 to vc1 when vc2 is dismissed by swiping down?

Thanks,

Edit --

Apologies for the lack of information, very new to swift so unsure of the correct question to ask in this situation.

To elaborate, the root of the issue at the moment is that vc2 is not dismissed programatically. ie there is currently no function called, it is simply dismissed by the user swiping down.

Is there some function that I can include to capture this dismissal, and use it to send data back to vc1?

I would prefer not to add any buttons to vc2 if possible.

Apologies again, and I appreciate all the help given already!

DankyKang
  • 25
  • 7
  • you can use delegate method to pass data back to preview view controller – Arun Apr 14 '20 at 13:22
  • https://www.hackingwithswift.com/example-code/system/how-to-pass-data-between-two-view-controllers – Dilan Apr 14 '20 at 13:34
  • The modern light-weight *swifty* way is a callback closure. – vadian Apr 14 '20 at 14:03
  • call back is called "Protocol" in iOS. Define your own protocol and var (people prefer to use "delegate") of the protocol in VC2. Set the var in VC1 as vc2.var = self before push/present VC2. In viewDidDisappear of VC2, call var.yourCallback() to let VC1 know w/ your VC2 data. – beshio Mar 03 '23 at 12:07

4 Answers4

1

Try This

class VCOne: UIViewController {

//Create a shared instance of VCOne

 static var sharedInstance:VCOne?

 //Let the data to be passed back to VCOne is of type string

  var dataToBePassedBack:String?

  override func viewDidLoad() {
    super.viewDidLoad()

   //set the sharedInstance to self
    VCOne.sharedInstance = self

    }

}

Class VCTwo:UIViewController{

 //function in which you are dismissing your current VC you can use the shared 
 instance to pass the data back

func dismissVC(){

  //before dismissing the VCTwo you can set the value for VCOne

VCOne.sharedInstance?.dataToBePassedBack = "data" 

}


}
Anmol Rattan
  • 137
  • 1
  • 8
  • Hi Anmol, thanks for the suggestion. Is there a way to call dismissVC when the user swipes down to dismiss VCTwo? Currently I have no function to dismiss this VC, its just swiped down by the user. Very new to swift so apologies for my ignorance! – DankyKang Apr 14 '20 at 14:41
  • You can detect when the controller is dismissed. Please check this reference [https://stackoverflow.com/questions/56568967/detecting-sheet-was-dismissed-on-ios-13] – Anmol Rattan Apr 14 '20 at 15:31
  • Ah ok, thats actually exactly what I needed to know. Thanks! – DankyKang Apr 15 '20 at 09:12
1
  • Using Protocol And Delegate You Do or Other Option is NSotificationcenter.
karthikeyan
  • 3,821
  • 3
  • 22
  • 45
0

One way yo do it is to create another file that it the controller of everything and then have a delegate that always notifies the view controllers when new changes are available. I will walk it through.

     protocol HeadControllerDelegate {
        // Create a function that sends out the data to the delegates when it is called
        // You can use your custom struct here to pass more data easly
        func didReciveNewData(myData: String?)
    }

    struct HeadController {

        // Create a shared instance so that the viewcontroller that conforms to the view as well as when we sends out the data the delegate is correct
        static var shared = HeadController()
        // Creates the delegate, every view can asign it to
        public var delegate: HeadControllerDelegate?

        // Add all your values here you want to pass back
        var myValue: String? {
            // The didSet gets called every time this value is set, and then is it time to call the delegate method
            didSet {
                // Calls the delegates didReciveMethod to notify the delegates that new data exsists
                delegate?.didReciveNewData(myData: myValue)
            }
        }
    }

Now in your viewcontroller class where you would like the data to be avaiable (as you said when you swipe down)

    class ViewController: UIViewController {

    // Here you create a property of the shared instance
    let headController = HeadController.shared

    override func viewDidLoad() {
        super.viewDidLoad()

        // Set yourself as the delegate for the headController delegate to recive data
        headController.delegate = self

    }

}

extension ViewController: HeadControllerDelegate {

    // here will the data be recived
    func didReciveNewData(myData: String?) {
        // handle the data here, you have now got newData

        print(myData)
    }
}

In the class where you want to pass data you just do it like this. The beauty of this is that you can have multiple classes or structs that writes to the head controllers data (just make sure you do it thought the shared instance). It is also a good pracice according to we to use the delegate pattern.

class Sender {

    var headController = HeadController.shared

    func sendData(data: String) {

        // Here you change the data of the headcontroller wich will send the data to all the delegates
        headController.myValue = data
    }
}

Hope this answer helps. If you have any questions please let me know.

UPDATE -- EASIER SOLUTION

Here is an easier solution but is less scalable as the previous one according to me.

In prepareForSegue simply pass over your current viewContorller as a field in the destination view controller. Then when viewDidDissapear in the new view controller you can simply pass back the data. Not to worry, I will show you!

In prepare for Segue

 override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let dc = segue.destination as? SecondViewController {
        dc.viewController = self
    }
}

And declare the secondViewContorller as following. The ViewDidDisappear method will be called when the view has dismissed, and therefore can you pass over the data to the view controller you have set before using the prepare for segue method.

    class SecondViewController: UIViewController {

    var viewController: UIViewController?

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

    override func viewDidDisappear(_ animated: Bool) {
        (viewController as? ViewController)?.value = 2
    }

}

Then you could update the UI using a didSet, which simply will be called when the property is set, which will be done in the view did disappear method.

var value: Int = 0 {
    didSet {
        print(value)
        text?.text = "\(value)"
    }
}

Hope this helps!

0

using protocol and delegate. first create a protocol in the vc2 like this

protocol sendData {
    func sendDataToNextVC(txt: String)
}  

class viewController2 : UIViewController {

    var dataDelegate : sendData?
    @IBOutlet weak var btn1 : UIButton!
       
    override viewDidLoad(){
       super.viewDidLoad()
       btn1.addTarget(self, action: #selector(someAction(_ :)), for: .touchUpInside)
    } 


    @objc func someAction(_ sender: UIButton){
         self.dataDelegate?.sendDataToNextVC(txt: "Hello world")
    }
}

now in viewController1 implement the protocol like this

extension ViewController1 : sendData {
    func sendDataToNextVC(txt: String){
         print(txt)
    }
}

And at viewDidLoad() of viewController1 make the delegate of viewController2 delegate to viewController1 as self like this

override viewDidLoad(){
    super.viewDidLoad()
    let vc2 = viewController2()
    vc2.dataDelegate = self
}