Reputation: 5255
I am trying to transfer data from the textfield of one View Controller to the label from another.
How can I call the View Controller instance from the code of the other View Controller? I'm working with storyboards thus I never created an instance of the View Controllers in the code? Are the instances automatically created? And what name do they have?
Thanks for your help!
Upvotes: 31
Views: 58646
Reputation: 92589
Add a new Cocoa Touch class file in your project, name it FirstViewController
and set the following code in it:
import UIKit
class 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 UIKit
class 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
.
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 UIKit
class 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 UIKit
protocol 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
.
Upvotes: 21
Reputation: 1142
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? YourViewController
viewController?.yourProperty = newValue
Keep in mind that this approach is rather "hacky" and probably violates the best coding practices.
Upvotes: 16
Reputation: 19969
You need to create a Segue between View Controllers:
ViewController A
.Control
, click ViewController A
, drag and drop the blue line to ViewController B
. If ViewController A
is embedded in a NavigationController
, select "show" from the menu that appears when you let go. Otherwise, select "present modally."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.
Upvotes: 6