How can I pass data to another controller when starting the ViewController?

I want to transfer my data from one ViewController

VC to another VC. Is it possible?

I tried the following method and had no success:

Click the button:

self.dismiss(animated: true) { 
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let controller = storyboard.instantiateViewController(withIdentifier: "EditViewController") as! EditViewController
        controller.segueArray = [values]
    }

      

when it EditViewController

appears again, mine segueArray

is nil

there.

How do I transfer my data from my ViewController

to EditViewController

when leaving?

+8


source to share


4 answers


The best way to pass data back to the previous view controller is through delegates ... when moving from ViewController A to B, pass the view controller A as a delegate, and in the viewWillDisappear method for ViewController B, call the delegate method in ViewController A. Protocols help define the delegate and required methods to be implemented by the previous VC. Here's a quick example:

Data transfer protocol:

protocol isAbleToReceiveData {
  func pass(data: String)  //data: string is an example parameter
} 

      

Viewcontroller A:



class viewControllerA: UIViewController, isAbleToReceiveData {

  func pass(data: String) { //conforms to protocol
  // implement your own implementation
   }

  prepare(for: Segue) {
    /** code for passing data **/
    let vc2 = ViewCOntrollerB()  /
    vc2.delegate = self   //sets the delegate in the new viewcontroller 
                          //before displaying
    present(vc2)
  }
}

      

Leaving view controller:

class viewControllerB: UIViewController {

  var delegate: isAbleToReceiveData

  viewWillDisappear {
      delegate.pass(data: "someData") //call the func in the previous vc
  }
}

      

+11


source


In the blocking completion block, you create a new instance of EditViewController. I am assuming another instance of EditViewController exists on the navigation stack, you need to find that instance and set the segueArray values. This can be achieved by iterating through your navigation stack view controllers, for example:

viewController.navigationController?.viewControllers.forEach({ (vc) in
    if let editVC = vc as? EditViewController {
        editVC.segueArray = ....
    }
})

      

But I would recommend using the delegate pattern like:

protocol EditViewControllerDelegate: class {
    func setSegueArray(segues: [UIStoryboardSegue])
}

      

In the viewcontroller (just call it ViewController) where the reject block is located, declare the delegate property:



class ViewController: UIViewController {
    weak var delegate: EditViewControllerDelegate?
    ....
}

      

Then, after presenting an instance (let's say from an EditViewController), the ViewController sets the delegate like this:

...
if let vc = presentingViewController as? ViewController {
    vc.delegate = self
}

      

And map the EditViewController to a delegate protocol like:

extension EditViewController: EditViewControllerDelegate {
    func setSegueArray(segues: [UIStoryboardSegue]) {
        // Do the data setting here eg. self.segues = segues
    }
}

      

+1


source


To detect when the back button is clicked on the view controller, I simply use:

override func didMove(toParentViewController parent: UIViewController?) {
    guard parent == nil else { return } // Back button pressed

    ... // Pass on the info as shown in you example
} // didMoveToParentViewController

      

0


source


Generic solution: (🔸 Swift 5.1)

/**
 * Returns a ViewController of a class Kind
 * ## Examples:
 * UIView.vc(vcKind: CustomViewController.self) // ref to an instance of CustomViewController
 */
public static func vc<T: UIViewController>(vcKind: T.Type? = nil) -> T? {
   guard let appDelegate = UIApplication.shared.delegate, let window = appDelegate.window else { return nil }
   if let vc = window?.rootViewController as? T {
      return vc
   } else if let vc = window?.rootViewController?.presentedViewController as? T {
      return vc
   } else if let vc = window?.rootViewController?.children {
      return vc.lazy.compactMap { $0 as? T }.first
   }
   return nil
}

      

0


source







All Articles