Not able to access container view's tableview controller elements - ios

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.

Related

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;

Pass data forward by Segue (objective-c)

I have 2 view controller
Main has a button
Detail has a label: lblDetail
I'm trying to pass data by segue : "sgPushDetail". When click on the button on Main, the label on Detail will be changed.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"sgPushDetail"]) {
DetailViewController *detail = segue.destinationViewController;
detail.lblDetail.text = #"you've already clicked";
}
}
But when i build, the label doesn't change. Please help me with this case!
The DetailViewController is not loaded when you are setting value for the label in prepareForSegue method. Do the following:
Create a property (i.e. NSString) in DetailViewController
Set the value for this property in prepareForSegue method
In viewDidLoad method of your DetailViewController, assign this property value to the label.

ios Navigation can't pass value to next Viewcontroller when I popViewController again

I have two ViewController (ViewController, ResultViewController).
There have three button in the ViewController,and there have a back button in ResultViewController.
In the ResultViewController I want to get the value from the ViewController passing.
So I add the below code in the ResultViewController
#interface ResultViewController : UIViewController
- (IBAction)backEvent:(id)sender;
#property (weak, nonatomic) IBOutlet UILabel *resultLb;
#property (strong, nonatomic) NSString *selectedVal;
#end
.m
- (void)viewDidLoad {
[super viewDidLoad];
[self.navigationController setNavigationBarHidden:YES animated:NO];
self.resultLb.text = self.selectedVal;
}
- (IBAction)backEvent:(id)sender {
[self.navigationController popViewControllerAnimated:NO];
}
In the ViewController have three button action:
- (void)viewDidLoad {
[super viewDidLoad];
[self.navigationController setNavigationBarHidden:YES animated:NO];
rvc = [self.storyboard instantiateViewControllerWithIdentifier:#"ResultViewController"];
}
- (IBAction)passAEvent:(id)sender {
rvc.selectedVal = #"A";
[self.navigationController pushViewController:rvc animated:NO];
}
- (IBAction)passBEvent:(id)sender {
rvc.selectedVal = #"B";
[self.navigationController pushViewController:rvc animated:NO];
}
- (IBAction)passCEvent:(id)sender {
rvc.selectedVal = #"C";
[self.navigationController pushViewController:rvc animated:NO];
}
When I first click the button A, that can correct pass the "A" value to the ResultViewController.
But when I click the back button in the ResultViewController.
Then click the B or C button action, that still pass the "A" value.
I see the log, that was not enter B, C event.
I try to run again program, when I click the first button with B button, It was correct enter and pass "B" value to ResultViewController.
But when I click the back button, then click the A or C button, it was not correct value in the ResultViewController.It still show "B" value.
I don't know why? how can I resolve the problem if not use delegate or notify?
Thank you.
----- edit ----
To the #Gaurav Singh
I am not find the option about the animate .
It's because you're keeping a strong reference to the UIViewController, via your variable rvc.
You're setting the value of resultLb in the viewDidLoad method of your view controller. When you push the view controller onto the stack, your view controller's setting the label by taking what's stored in it's variable selectedVal.
When you pop the view controller from the stack, because you've got it stored in a variable, it won't get unloaded from memory. It still exists. You may be setting selectedVal again when tapping the second button, however viewDidLoad isn't going to get run again, as it's not getting re-instantiated.
What you could do is overload setSelectedVal on ResultViewController as follows:
- (void)setSelectedVal:(NSString *)selectedVal {
_selectedVal = selectedVal;
self.resultLb.text = selectedVal;
}
This way, when you set selectedVal from the calling view controller, the above method will be run, setting the value of your property in ResultViewController, whilst also modifying your label.
EDIT - Better still:
Rather than setting the value of the label in viewDidLoad:, do it in viewWillAppear: instead. This way, you don't need to override any setters or anything like that. When viewWillAppear is called, it'll read the string you've set and set the label's text accordingly.
Hope this helps!
You are just making it complex. I would do it like this:
First I will connect create a storyboard segue from ViewController to Result Controller (View Controller to View Controller segue) and assign a suitable identifier to that segue (say "resultSegue")
then following code would work
- (IBAction)passAEvent:(id)sender {
[self performSegueWithIdentifier:#"resultSegue" sender:#"A"];
}
- (IBAction)passBEvent:(id)sender {
[self performSegueWithIdentifier:#"resultSegue" sender:#"B"];
}
- (IBAction)passCEvent:(id)sender {
[self performSegueWithIdentifier:#"resultSegue" sender:#"C"];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue
sender:(id)sender {
if([segue.identifier isEqualToString:#"resultSegue"]){
ResultViewController *rvc = segue.destinationViewController;
rvc.selectedVal = sender; //Here SENDER will have value: A,B or C which we have passed in performSegueWithIdentifier:sender: method
}
}
Edit: code in prepareForSegue:sender: method modified so that it check the segue identifier before working on destinationViewController
First, you should give the segue an "id",like "resultSegue".
Then, use the code:
- (void)prepareForSegue:(UIStoryboardSegue *)segue
sender:(id)sender
{
if([segue.identifier isEqualToString:#"resultSegue"]){
ResultViewController *rvc = segue.destinationViewController;
rvc.selectedVal.text = someUILabel.text;
than use the [self.navigationController pushViewController:rvc animated:NO];//.........
}
I will give you more detail when I m at home, if you don`t solve the problem....
Thanks!
put
rvc = [self.storyboard instantiateViewControllerWithIdentifier:#"ResultViewController"];
in viewWillAppear

IOS Segue not able to set label directly

I am having two view controllers 'FirstViewController' and 'SecondViewController'. From first view controller it will take input from a text field ,process it and display accordingly in the second view. But I am having a problem while setting label value directly.
#interface SecondViewController : UIViewController
{
NSString *numPlate;
IBOutlet UILabel *output;
};
#property(strong,nonatomic) NSString *numPlate;
#property(strong,nonatomic) IBOutlet UILabel *output;
#end
The main file for FirstViewController.m with prepare for segue is as
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([[segue identifier] isEqualToString:#"Change"])
{
SecondViewController *svc = (SecondViewController *)[segue destinationViewController];
svc.numPlate = input.text;
NumberPlate *numPlate=[[NumberPlate alloc]init];
[numPlate setPlate:input.text];
NSInteger flag=[numPlate checkValidity];
if(flag==0)
{
svc.output.text =#"Invalid License";
}
else
if([numPlate getArea]==NULL||[numPlate getRegOffice]==NULL)
{
svc.output.text =#"Data not found";
}
else
{
svc.output.text =#"VALID License";
}
}
}
But when the action is performed its not working.The label is not changing.
When i used svc.numPlate instead of svc.output.text and in the SecondViewController viewDidLoad method and i used
- (void)viewDidLoad
{
[super viewDidLoad];
output.text=numPlate;
}
Everything is fine with this. Whats wrong in first method??
You will not be able to assign value directly to UILabel of second VC as view is not yet loaded into view hierarchy at this point.
So view cannot render the value assigned prior to it.
On the other hand, holding value in NSString and assigning same on viewDidLoad is working as now your view is in view hierarchy and loaded into memory.
At the time when you push SecondViewController, the SecondViewController's view hasn't been loaded yet, so you can't access its views. You need to create NSString properties in SecondViewController and pass a string to SecondViewController' NSString Object. Then in SecondViewController's viewDidLoad method, use those properties to populate the labels (which will have been loaded by the time viewDidLoad runs).
The initialisation of controller is different and presentation of its view is different process even if the viewController has been initialise its view will not because pushing the controller has not performed and controller dont know he need to load the view.. so we pass the data to controller and it load when view appears... like below code
#interface SecondViewController : UIViewController{
NSString *strMessage;
}
#property(nonatomic,retain) NSString *strMessage;
#end
SecondViewController.m
#synthesize strMessage;
- (void)viewDidLoad {
Nslog(#"%#",strMessage);
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([[segue identifier] isEqualToString:#"Change"])
{
SecondViewController *svc = (SecondViewController *)[segue destinationViewController];
NSString *message = [NSString stringWithFormat:#"Check out %#", nameLb.text];
svc.strMessage=message;
}

Set UITextField text property in prepareForSegue

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.

Resources