Set UITextField text property in prepareForSegue - ios

I have a textField in my ViewController1. I have a push segue to my ViewController2 which also has a textField. I need to set the textField.text in my ViewController2 to be equal to the text in the textField in my ViewController1. Here's the code I have:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqual:#"ViewController2"])
{
ViewController2 *VCT = [segue destinationViewController];
VCT.title = #"View Controller #2";
VCT.textField.text = self.textField.text;
}
}
The title setter works just fine. Why is the textField not working?

You cannot set the text of the UITextField (and any other components like UILabel and UITextView) in the prepare for segue, because all view components of the recently allocated controller are not initialized yet (at this time, they are all nil), they only will be when the viewController is presented (and it's view loaded).
You have to create a NSString property in the presented viewController, and then, somewhere inside your another view controller, like viewDidLoad, set the text of the textField as this property value.
Like this:
In the viewController that will present the another viewController:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"ViewController2"])
{
ViewController2 *vc2 = [segue destinationViewController];
vc2.myString = self.textField.text;
}
}
And inside the presented viewController:
- (void)viewDidLoad
{
[super viewDidLoad];
(...)
self.textField.text = self.myString;
}

Check and see if "VCT.textField" is not nil at that point. I suspect that you'll find it is nil.
You either need to expose it via "#property (strong) IBOutlet UITextField * textField" or you need to store the string somewhere else (e.g. a "NSString" property?) which then loads the text field when the view is fully loaded.

Related

Not able to access container view's tableview controller elements

I have a view controller (vc1) which has a container view and below that it has a save button . Container view is embed segued to tableview controller(tvc1) having static cells . Each cell has labels and textfields.
I am trying to get the contents of textfields in tvc1 in vc1 .
I tried two methods :
Preparefor segue in vc1:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NSLog(#"prepare for segue called in settings view controller.");
NSString * segueName = segue.identifier;
if ([segueName isEqualToString: #"embedseguesettings"]) {
NSLog(#"embed segue called ");
settingsTableViewController *tvc1 = (settingsTableViewController *)segue.destinationViewController;
tvc1.surlTextField.text = #"i got u ";
}
}
i am getting print for "embed segue called ", but the textfield in tvc1 is not updated with my text "i got u". Have i got the tvc1 object properly ?
Instantiate tvc1 in vc1:
- (IBAction)save:(id)sender {
settingsTableViewController *tvc1 = [self.storyboard instantiateViewControllerWithIdentifier:#"settingsTableView"];
NSLog(#"surl textfeild = %#",tvc1.surlTextField.text);
}
But i always get null as output. i type some text to surl textfield an press save . i always get null.
settingsTableViewController is the container view's table view controller and i have only set the no of sections and no of rows in that class. Do i need to dequeue cells , i should not be ? , its a static tableview.
The problem is that you're setting the textField value in tvc1 before the view has loaded.
You should add a property in tvc1…
#property (nonatomic, strong) NSString* someText;
then in your prepareForSegue method, assign to someText and also keep a reference to tvc1
if ([segueName isEqualToString: #"embedseguesettings"]) {
settingsTableViewController *tvc1 = (settingsTableViewController *)segue.destinationViewController;
tvc1.someText = #"i got u ";
self.tvc1 = tvc1
}
and in your tvc1 viewDidLoad
tvc1.surlTextField.text = self.someText
Then in your save method:
- (IBAction)save:(id)sender {
// Don't instantiate a new tvc1
NSLog(#"surl textfeild = %#",self.tvc1.someText);
}
As per - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender flow its still not allocated it outlets so...
The UIViewController isn't loaded at that moment.
You need to set #property values and access that in the viewDidLoad() method
and setup your textFiled text accordingly.

Can't set the properties for the next view using prepareForSegue: sender:

I'm using Objective-C. I set a segue from a table view cell to a new view controller, and I want to set the properties for the new view controller using this method:
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString: #"detail"]){
if([segue.destinationViewController isKindOfClass:[detailViewController class]]){
detailViewController *detail = (detailViewController *)segue.destinationViewController;
detail.label.text = #"QQQQQ";
}
}
I've set the segue's identifier to #"detail" already, and also connected the label code with the view controller in storyboard. But when I run this in my simulator, the label would never change.
at the time when prepareForSegue is called the destinationviewcontroller's outlets are not set yet.
what you have to do is create a property in your detailViewController class like
#property (copy, nonatomic) NSString *detailText;
then in prepareForSegue:
detailViewController *detail = (detailViewController *)segue.destinationViewController;
detail.detailText = #"QQQQQ";
and in your detailViewControllers viewDidLoad:
self.label.text = self.detailText;

IOS Objective C - error while passing parameter between two view controllers

I have two viewControllers :
RegisterViewController & Register2ViewController
I have a segue from RegisterViewController to Register2ViewController.
I want to set the value of a the textfielduser in Register2ViewController with a value that the user entered in a the textfieldemail in RegisterViewController.
so far here is what i've done.
in RegisterViewController.m
- (IBAction)NextPage:(UIButton *)sender {
[self performSegueWithIdentifier:#"toRegister2" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"toRegister2"]) {
Register2ViewController *controller = (Register2ViewController *)segue.destinationViewController;
controller.user.text = self.email.text;
}
but when I run and fill the values of textfields in RegisterViewController and go over to Register2ViewController the textfield user is empty, can you help me please? Thank you
controller.user.text = self.email.text;
At this time, the Register2ViewController is not loaded in the memory yet, that's why you are facing this issue.
Keep a NSString property in Register2ViewController.h and set the value of that string here.
Then, in viewDidLoad of Register2ViewController, set that string as text of UITextField.
Instead of directly passing value to textField, try passing text using NSString. Declare #property (strong,nonatomic) NSString *userName; in Register2ViewController. Then pass value to string like
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"toRegister2"]) {
Register2ViewController *controller = (Register2ViewController *)segue.destinationViewController;
controller.useName= self.email.text;
}
Then in viewDidLoad of Register2ViewController ,set string on textField like this self.user.text=self.userName.
Try doing this.

Loading another view in the same viewController clears non UI properties

I have a UIViewController controlling several different views in Xcode. I want to set a label on the incoming view using information from the current view. I know labels and other UI elements get reset when the view is loaded, but my non UI #property is being set to nil as well.
Here is my property:
#property (strong, nonatomic) NSString* username;
Here is the code that sets it:
//NSLog(#"%#",dict);
if ([dict[#"login"] intValue]){
[self performSegueWithIdentifier:#"JoinSuccess" sender:sender];
self.username = dict[#"user"];
Here is the code that tries to use it:
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"%#", self.username);
self.welcomeLabel.text = [NSString stringWithFormat:#"Welcome, %#",self.username];
}
I've tried setting username both before and after performSegueWithIdentifier, but in either case when I try to reference it in viewDidLoad the value is nil. Any idea as to why it's reseting my #property? My guess is maybe it's creating a new instance of my viewController. If that's the case, how can I pass the needed variable?
As you said the viewController will be created again when ever you call performSegueWithIdentifier. You could set the value in the new instance. You can do this in
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
YourViewController *vc = [segue destinationViewController];
vc.username = dict[#"user"];
}
you have to add another method to pass value from one view controller to another view controller .
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
nextViewcontroller *nextViewcontrollerObjt = [segue
destinationViewController];
// apply setter to set value of next view
nextViewcontrollerobject.title = nextViewControllerTitleString;
nextViewcontrollerobject.variable_1= currentView_variable1;
nextViewcontrollerobject.variable_2 =currentView_variable2;
}

Pass info to viewcontroller on storyboard

I'm new using storyboards and I'm facing this situation: A uinavigationcontroller contains a view controller (root controller) which contains ten buttons linked each one of then through storyboard to the same view controller.
The behavior of the second view controller depends on the button tapped in the first view controller, but how can identify which button is tapped (like tag value) and pass this info to second view controller?
Thank you.
To add on Daniel's answer:
First, add a public property onto your secondVC that is accessible from your first VC:
#interface SecondViewController : UIViewController
#property (nonatomic) int buttonTagClicked;
#end
You need to set tags up on your UIButtons. This is either done in storyboard or programmatically in your code. I would create a generic IBAction that each button is linked to. You can extract the tag off the button through the sender parameter later.
- (IBAction)buttonClicked:(id)sender
{
[self performSegueWithIdentifier:#"pushSegue" sender:sender];
}
That is linked up to
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"pushSegue"]) {
SecondViewController *destinationVC = (SecondViewController *)[segue destinationViewController];
UIButton *selectedButton = (UIButton *)sender;
destinationVC.buttonTagClicked = selectedButton.tag;
}
}
You can set a segueIdentifier for each connection. Then in your ViewController you could trigger an action based on the identifier you set.
e.g.:
If you select your connection in storyboard you can name it:
And in your ViewController you can trigger an action based on the identifier like this:
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"segue1"]) {
UIViewController *destinationVC = [segue destinationViewController];
destinationVC.property = ...;
}
}

Resources