This question already has answers here:
Passing data between view controllers
(45 answers)
Closed 6 years ago.
I am trying to send a BOOL value from
ViewController A to ViewController B.
On ViewController A, dashboard.skip shows YES, but on
ViewController B, self.skip shows NO.
- (IBAction)skipToDashboard:(UIButton *)sender {
ViewController B *vc=[[ViewController B alloc]init];
vc.presentButtonTag=sender.tag;
self.fromSkip=YES;
vc.skip=self.fromSkip;
}
In ViewController B:
#property (nonatomic,assign) BOOL skip;
There are 2 ways to pass your data from First screen to 2nd screen.
1st Way:
You can pass your data by creating VC object and assign value in it and push to next screen like below example.
Code :
//Initilize view controller from storyboard id.
ViewController *objViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"ViewController"];
//Assign value
objViewController.presentButtonTag=sender.tag;
self.fromSkip=YES;
objViewController.skip=self.fromSkip;
//Push view
[self.navigationController pushViewController:objViewController animated:YES];
2nd Way:
By Storyboard you can set segue action on button and in prepare segue method you need to pass your data like this.
Code:
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
if ([segue.identifier isEqualToString:#"ViewController"]) {
ViewController *objViewController = (ViewController*)segue.destinationViewController;
objViewController.selectedTag = ((UIButton*) sender).tag;
//Assign value
objViewController.presentButtonTag=sender.tag;
self.fromSkip=YES;
objViewController.skip=self.fromSkip;
}
}
Now you can check your scenario in both condition I think you are pushing to next screen by storyboard so use 2nd Way.
Let me know if you need more help.
Try to define BOOL property and set value either true or false.
For Ex: Appdelegate declare property and then use
#property (nonatomic) BOOL fromSkip;
Related
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
This question already has answers here:
Passing data between view controllers
(45 answers)
Closed 8 years ago.
This is the scene of my storyboard.
UINavigationController -> UITableViewController -> push segue -> UIViewController
I know how to pass the data of UITableViewController to UIViewController.
But, how can I pass the data back to the UITableViewController?(UIViewController has a navigation bar with a back button)
You can do it through the use of delegation.
When you pass data of UITableViewController to UIViewController, you can set a delegate on UIViewController. Whenever you want to pass data back to UITableViewController, you can call the delegate and pass in the data
Here's a more concrete example in code
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:#"YOUR_SEGUE_NAME_HERE"])
{
// Get reference to the destination view controller
UIViewController *vc = [segue destinationViewController];
// Pass the UITableViewController to the UIViewController
[vc setDelegate:self];
}
}
Create a method on UITableViewController that takes data from UIViewController (example: -(void)processDataFromUIViewController:(NSString *)string)
Now when you want to pass data back to UITableViewController, call [delegate sendDataFromUIViewController:#"data"]
I'm trying to make a form that one of the filed takes value from a two level selections' result.
The main progress will something like:
EditViewController ===> CategoryViewController (which embedded inside a NavigationController by storyboard and popped up as a modal view) ===> SubCategoryViewController (Which will be pushed to NavigationController).
Now I have a problem. After user tap to select a value in SubCategoryViewController, I'm supposed to dismiss SubCategoryViewController and return the value to EditViewController. But I don't know exactly how.
Please suggest any solution.
Thank you.
EDIT:
Every one of those view controllers should have a public property for a weak reference to a model object that represents whatever is being edited.
So every ____ViewController.h file would have:
#property (weak, nonatomic) CustomItem *item.
in its interface (assuming a strong reference is somewhere in some data store or array of all the items).
When EditViewController is preparing for the segue to show CategoryViewController modally, it should assign that same reference to CategoryViewController's item property after assigning any data entered in EditViewController's form to item:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
//TODO: assign data from controls to item, for example:
//self.item.title = self.titleField.text;
CategoryViewController *vc = (CategoryViewController *)segue.destinationViewController
vc.item = self.item; //pass the data model to the next view controller
}
Likewise for the segue from CategoryViewController to SubCategoryViewController. This ensures that every ViewController is editing the same object in memory. When you dismiss SubCategoryViewController (assuming somewhere in all of this CategoryViewController was already dismissed), viewWillAppear: will be called on EditViewController- there you can refresh any changes made in the modal views to the item property, just like you would when first displaying the view (it's actually the same method that's called):
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.titleField.text = self.item.title;
self.categoryLabel.text = self.item.category;
self.subcategoryLabel.text = self.item.subcategory;
//etc....
}
I have two view controllers inside a Navigation Controller.
In the first view controller I have two buttons. Both of them call the second view controller using a Push segue, but:
I need to know which button sent me in the second view controller. How?
In the second view controller I have a UIDatePicker and a Button "Ok": how can I send the chosen date to the first view controller when Ok is pressed? (And how do I receive them?)
EDIT:
I don't know if my problem is clear: now I know how to pass data from the first view controller to the second view controller with prepareForSegue, but what I really need is to pass data (the picked date) from the second view controller to the first, and how can I do it without a prepareForSegue (when Ok is pressed)?
EDIT2:
I made it. It was so simple, guys...
I decided to use modal segue:
Firstviewcontroller.h:
+(FirstViewController *)getInstance;
Firstviewcontroller.m:
static FirstViewController *instance =nil;
+(FirstViewController *)getInstance
{
return instance;
}
and in its ViewDidLoad:
instance = self;
Secondviewcontroller.m, in the OkButton IBAction:
SecondViewController *secondViewController = [SecondViewController getInstance];
//...
//modify what I need to modify in secondviewcontroller
//...
[self dismissModalViewControllerAnimated:YES];
That's it.
Thank you all anyway.
Assign Identifier to each segue in storyboard and implement
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:#"YOUR_SEGUE_NAME_HERE"])
{
// Get reference to the destination view controller
YourViewController *vc = [segue destinationViewController];
[vc setDelegate:self];
// Pass any objects to the view controller here, like...
[vc setMyObjectHere:object];
}
}
For more info about How to use storyboard and pass value check this article or this discussion on stackoverflow
for the second question you can use delegate pattern
IN SecondViewController.h
#protocol SomethingDelegate <NSObject>
- (void)dateChanged:(NSString *)dateStr; //you can use NSDate as well
#end
#interface ViewController2 : UIViewController
#property(weak) id<SomethingDelegate> delegate;
#end
in .m file
-(void) OkClicked{
[_delegate dateChanged:#"YOUR_DATE_VALUE"];
}
In FirstViewController.h
#import "SecondViewController.h"
#interface FirstViewController : UIViewController<SomethingDelegate>
in .m
-(void)dateChanged:(NSString *)dateStr{
// do whatever you need with dateStr
//also i made some change in prepareForSegue method
}
Note:- take care your naming convenes for VC
just pass the button id to the second viewcontrol.
use delegates to sent the data from second viewcontroller back to first view controller
regards
Johan
Tell me, please, how should i transfer several variables from one ViewController to another?
For example, i have
ViewControlle.m
- (void) transferVar{
int a = 10;
int b = 11;
}
and i want to transfer them to another ViewController (SecondViewController.m). What should i do?
you can add a property on the second view controller for every variable you want to pass (or an array to contain them all), then if you are making the segue on the storyboard use the method
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
and inside it make this
SecondViewController *svc = (SecondViewController *) segue.destinationViewController;
There you have the view controller you want to pass values so only save it
svc.yourArray = #[[NSNumber numberWithInt:a],[NSNumber numberWithInt:b]];
Also it is highly recommendable to add a segue identifier to the storyboard segue and check
if([segue.identifier isEqualToString: #"theIdentifier"])
to be sure it is the segue that you wanted
Now on the viewDidLoadMethod you can use them.
If you are not using the storyboard segue just assign the value after initiating the view.