Access the instance of a Viewcontroller from another in swift
1. If the view controller containing the textfield can call (with a segue) the view controller containing the label...
Add a new Cocoa Touch class file in your project, name it FirstViewController
and set the following code in it:
import UIKitclass FirstViewController: UIViewController { @IBOutlet weak var textField: UITextField! // FIXME: link this to the UITextField in the Storyboard!!! override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { let controller = segue.destinationViewController as! SecondViewController controller.text = textField.text } }
Add a new Cocoa Touch class file in your project, name it SecondViewController
and set the following code in it:
import UIKitclass SecondViewController: UIViewController { var text: String? @IBOutlet weak var label: UILabel! // FIXME: link this to the UILabel in the Storyboard!!! override func viewDidLoad() { super.viewDidLoad() label.text = text } }
In the Storyboard, embed the first view controller in a UINavigationController
. Link the first view controller to the second with a UIButton
or a UIBarButtonItem
. Set the name of the first view controller to FirstViewController
and the name of the second view controller to SecondViewController
. Create a UITextField
in the first view controller. Create a UILabel
in the second view controller. Link the textfield and the label to their respective declarations in FirstViewController
and SecondViewController
.
2. If the view controller containing the label can call (with a segue) the view controller containing the textfield...
Here, this is a perfect protocol/delegate case. You may find a lot of stuff on StackOverflow dealing with this. However, here is a rough example.
Add a new Cocoa Touch class file in your project, name it FirstViewController
and set the following code in it:
import UIKitclass FirstViewController: UIViewController, DetailsDelegate { @IBOutlet weak var label: UILabel! // FIXME: link this to the UILabel in the Storyboard func updateLabel(withString string: String?) { label.text = string } override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { let controller = segue.destinationViewController as! SecondViewController controller.delegate = self } }
Add a new Cocoa/Cocoa Touch class file in your project, name it SecondViewController
and set the following code in it:
import UIKitprotocol DetailsDelegate: class { func updateLabel(withString string: String?)}class SecondViewController: UIViewController { weak var delegate: DetailsDelegate? @IBOutlet weak var textField: UITextField! // FIXME: link this to the UITextField in the Storyboard override func viewWillDisappear(animated: Bool) { super.viewWillDisappear(animated) delegate?.updateLabel(withString: textField.text) }}
In the Storyboard, embed the first view controller in a UINavigationController
. Link the first view controller to the second with a UIButton
or a UIBarButtonItem
. Set the name of the first view controller to FirstViewController
and the name of the second view controller to SecondViewController
. Create a UILabel
in the first view controller. Create a UITextField
in the second view controller. Link the textfield and the label to their respective declarations in FirstViewController
and SecondViewController
.
Imanou Petit and Oscar Swanros already answered correctly. However there is an alternative which is rather "hacky" that I had to use to transfer data between 2 view controllers without a segue connecting them.
To obtain the root view controller of your app you can do:
UIApplication.sharedApplication().windows[0].rootViewController
From there you can get any view controller you want. For instance, if you want the second child view controller of the root view controller then you would do:
let viewController = UIApplication.sharedApplication().windows[0].rootViewController?.childViewControllers[1] as? YourViewControllerviewController?.yourProperty = newValue
Keep in mind that this approach is rather "hacky" and probably violates the best coding practices.
You need to create a Segue between View Controllers:
- On your Storyboard, select
ViewController A
. - While holding the
Control
, clickViewController A
, drag and drop the blue line toViewController B
. IfViewController A
is embedded in aNavigationController
, select "show" from the menu that appears when you let go. Otherwise, select "present modally." - Select the Segue on your Storyboard, and on the Utilities Panel, go to the Attributes Inspector and assign an Identifier for your segue (e.g.: "DetailSegue").
Now, when you want to trigger the segue on ViewController A
, you just need to call (maybe on the tap of a button):
@IBAction func buttonTapped() { self.performSegueWithIdentifier("DetailSegue", sender: self)}
To pass a value to ViewController B
, override the prepareForSegue:sender
method on ViewController A
:
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) { if segue.identifier == "DetailSegue" { var viewControllerB = segue.destinationViewController as ViewControllerB viewControllerB.text = self.textField.text }}
Pretty straightforward.
Note that for this to work, your ViewController B
class should look something like this:
class ViewControllerB: UIViewController { ver label = UILabel(...) var text: String? override func viewDidLoad() { super.viewDidLoad() label.text = text! }}
Hope this helps.