Mohan Ramanathan
Mohan Ramanathan

Reputation: 2209

Unable to set the text for UITextfield from other class

I am trying to set the text for the UITextField in the SecondViewController from the FirstViewController using the below code:

// First ViewController
@IBAction func buttonAction(_ sender: Any) {
    let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "SecondViewController") as? SecondViewController
    viewController?.sampleTxtField?.text = "world"
    if let navigator = self.navigationController {
        navigator.pushViewController(viewController!, animated: true)
    }
}


// Second ViewController
 @IBOutlet weak var sampleTxtField: UITextField?
override func viewDidLoad() {
    super.viewDidLoad()
    print("the textfield value is,\(String(describing: sampleTxtField?.text))")
}

In the log I am getting: "the textfield value is,Optional("")"

I think I am doing some silly mistake. I checked many questions but I am unable find any solution.

Upvotes: 0

Views: 901

Answers (3)

Suhit Patil
Suhit Patil

Reputation: 12023

When you instantiate a UIViewController from storyboard using instantiateViewController(withIdentifier:) method it creates a new instance of ViewController and returns it but the UIView and it's elements are not initialised until the UIView is loaded in memory.

ViewDidLoad() gets called when the view controller’s content view (the top of its view hierarchy) is created and loaded from a storyboard. The view controller’s outlets are guaranteed to have valid values by the time this method is called.

So you need to configure your UI element values in ViewDidLoad to have a proper value to these elements.

In you case viewController?.sampleTxtField?.text = "world" line will not work as Views not yet loaded in memory. To resolve this you need to define a String variable and assign the value after the ViewController is initialised. Then in ViewDidLoad you can assign the String value to the UITextField text property.

class SecondViewController: UIViewController {

   @IBOutlet weak var sampleTxtField: UITextField!
   var sampleText: String? //it can be var also with default value

   func viewDidLoad() {
     super.viewDidLoad()
     //assign the textField Value here
     if let text = sampleText {
        self.sampleTxtField.text = text 
     }
   }
}

Now in FirstViewController you can assign the sampleText property like

@IBAction func buttonAction(_ sender: Any) {
    guard let secondViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "SecondViewController") as? SecondViewController else {
      fatalError("No ViewController with Identifier "SecondViewController")
    }
    secondViewController.sampleText = "world"
    if let navigator = self.navigationController {
        navigator.pushViewController(secondViewController, animated: true)
    }
}

Upvotes: 1

Make a variable in second viewController like this :

var sampleText: String!

And in viewDidLoad() of the second view controller write this:

sampleTxtField?.text = sampleText

and in first view controller replace viewController?.sampleTxtField?.text = "world" line with this:

viewController.sampleText = "world"

This is the standard way to set a value to a textField from another class.

Upvotes: 1

Mani
Mani

Reputation: 17585

Your code is wrong.

let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "SecondViewController") as? SecondViewController
    viewController?.sampleTxtField?.text = "world"

In above statment, view's not get loaded in UI so sampleTxtField always will be nil, Instead create a property in SecondVC, var sample : String? and assign it as above. Then in SecondVC's viewDidload, assign the value as textField.text = sample

// First ViewController

@IBAction func buttonAction(_ sender: Any) {
    let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "SecondViewController") as? SecondViewController
    viewController?.sample = "world"
    if let navigator = self.navigationController {
        navigator.pushViewController(viewController!, animated: true)
    }
}

// Second ViewController

@IBOutlet weak var sampleTxtField: UITextField?
var sample : String?
override func viewDidLoad() {
    super.viewDidLoad()
sampleTxtField.text =  sample
    print("the textfield value is,\(String(describing: sampleTxtField?.text))")
}

Upvotes: 3

Related Questions