Pass data between view controllers - objective-c

I’m still fairly new to Objective C and xCode so please forgive me.
I have two view controllers setup in my storyboard and im using the following code to move to another:
UIStoryboard * storyBoard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController * viewController = [storyBoard instantiateViewControllerWithIdentifier:#"stageOne"];
[self presentViewController:viewController animated:YES completion:nil];
Now this works great though in the class controlling the second view controller I have a property setup that Im attempting to send data to. I was attempting the following:
UIStoryboard * storyBoard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController * viewController = [storyBoard instantiateViewControllerWithIdentifier:#"stageOne"];
viewController.forename = #"Hello World";
[self presentViewController:viewController animated:YES completion:nil];
Though this does not work and all I get is an error "Propert 'forename' not found on object of type 'UIViewController'".
Any help is appreciated and if you are able to leave me with some example code that would be fantastic.

The problem with your code is your accessing the uicontrols which are not yet created in the memory. You have to change the order of the execution of your statements like this...
UIStoryboard * storyBoard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
holidayQuestion * viewController = [storyBoard instantiateViewControllerWithIdentifier:#"stageOne"];
[self presentViewController:viewController animated:YES completion:nil];
viewController.forename = #"Hello World";

Basically, for pass data between 2 controllers, you can use 2 design patterns: Delegation or Observer.
In your case, you use delegate. Do you have public property with name forename in your header file?

Related

Initializing and passing values between ViewControllers

I have two UIViewControllers: TimerViewController and EfficiencyViewController (For simplicity's sake, we will call them TVC and EVC)
I am trying to pass certain values (2 NSString objects, 1 NSTimeInterval)from TVC to EVC when a button is pressed. EVC needs to be intialized and pop up upon pressing the button.
Overall, I have tried two methods.
1. Directly passing the values (In TVC)
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
EfficiencyViewController *efficiencyViewController = [storyboard instantiateViewControllerWithIdentifier:#"EfficiencyView"];
efficiencyViewController.category = _categoryLabel.text;
efficiencyViewController.desc = _descriptionTextField.text;
efficiencyViewController.duration = [_timer getInterval];
efficiencyViewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentViewController:efficiencyViewController animated:YES completion:NULL];
Problem: When I instantiate EVC, the values I held in TVC are reset, so basically no data is passed. (I think this is because EVC actually pops up on the screen)
2. Building a custom init method
TVC
EfficiencyViewController *efficiencyViewController = [[EfficiencyViewController alloc] initWithName:_categoryLabel.text desc:_descriptionTextField.text duration:[_timer getInterval]];
[self presentViewController:efficiencyViewController animated:YES completion:NULL];
EVC initWithName method implementation
- (id)initWithName:(NSString *)category desc:(NSString *)theDesc duration:(NSTimeInterval)theDuration {
// self = [super initWithNibName:#"EfficiencyViewController" bundle:nil];
if (self != nil) {
_category = category;
_desc = theDesc;
_duration = theDuration;
}
return self;
}
Problem: The values are simply not being passed. And also in this way, EVC is missing some major components, such as a button and a text label.
If you have these in a storyboard, you should be using a storyboard segue, and in TVC's prepareForSegue(), you get the destination view controller (i.e. EVC) from the segue object, and that's where you set EVC's properties.
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main"
bundle:nil]; EfficiencyViewController *efficiencyViewController =
[storyboard
instantiateViewControllerWithIdentifier:#"EfficiencyView"];
efficiencyViewController.category = _categoryLabel.text;
efficiencyViewController.desc = _descriptionTextField.text;
efficiencyViewController.duration = [_timer getInterval];
efficiencyViewController.modalTransitionStyle =
UIModalTransitionStyleCoverVertical;
Use self instead of _, see this link https://stackoverflow.com/a/30901681/4912468

Change to another View Controller when pressing cell of UITableView

Hi I have a uitableview on my view controller and I want to go to another view controller when a cell is pressed, I read a couple of tutorial but all where from a table view controller.
Here is the code I have, it doesn't do anything when I pressed the cell.
EDIT: I decided to create a custom button on the cell and from there go to the detail view
Here is what I put on the button, I get a thread 1: breakpoint 1.1 error on the second line:
- (IBAction)buttonSelected3:(id)sender {
UIStoryboard *storyBoard; storyBoard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
InfoFarmaciaViewController *vc = (InfoFarmaciaViewController *)[storyBoard instantiateViewControllerWithIdentifier:#"InfoFarmaciaViewController"];
[self.navigationController pushViewController:vc animated:NO];}
You don't have to release the variable, ARC will take care of that. Just remove that line? And don't set it to null. Just push it, then you are done.
Are you using storyboard for that? - i assume not, change your views to storyboard and do the following:
UIStoryboard *storyBoard;
storyBoard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:nil];
CustomViewController *vc = (CustomViewController *)[storyBoard instantiateViewControllerWithIdentifier:#"idofthestoryboardview"];
[self.navigationController pushViewController:vid.fileViewController animated:YES];

Changing View Controllers - SIGABRT

I am trying to move from one view controller to another when a button is pressed, but it is giving me "sigabrt" error.
This is my code:
-(IBAction)buttonPressed:(id)sender{
StatsViewController *myStats = [self.storyboard instantiateViewControllerWithIdentifier:#"StatsViewController"];
[self presentViewController:myStats animated:YES completion:nil];
}
The only reason i am doing it this way is because i need to pass data forward from one view controller to the next.
I also checked my storyboard there are no connections between the two view controllers (just the above code).
However, when i remove the above code and connect the two view controller using the "control drag" method on the storyboard, it works. no error..
Make sure that the storyboard instance is not nil and and the Storyboard Id is set properly
-(IBAction)buttonPressed:(id)sender{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle: nil];
StatsViewController *lvc = [storyboard instantiateViewControllerWithIdentifier:#"StatsViewController"];
[self.navigationController pushViewController:lvc animated:YES];
}

Call storyboard scene programmatically (without needing segue)?

I have a modal storyboard scene that I want to be accessible to all my other scenes. Creating a modal segue to it from every scene on my storyboard creates a big mess of strings going everywhere. Is there a way that I leave off the segues and call the scene programmatically instead?
Basically I want to do something like this:
MyNewViewController *myNewVC = [[MyNewViewController alloc] init];
[self presentModalViewController:myNewVC animated:YES];
except instead of creating and pushing a view controller class, I want to do a modal transition to an "isolated" (not connected with a segue) storyboard scene.
Yes you can. Do something like this to get access to the VC, then just Modal Push it:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:nil];
MyNewViewController *myVC = (MyNewViewController *)[storyboard instantiateViewControllerWithIdentifier:#"myViewCont"];
Note: the method presentModalViewController:animated is deprecated in iOS 6.
The new code should read:
NSString * storyboardName = #"MainStoryboard_iPhone";
NSString * viewControllerID = #"ViewID";
UIStoryboard * storyboard = [UIStoryboard storyboardWithName:storyboardName bundle:nil];
MyViewController * controller = (MyViewController *)[storyboard instantiateViewControllerWithIdentifier:viewControllerID];
[self presentViewController:controller animated:YES completion:nil];
In the storyboard give your view controller an identifier (under the Attributes Inspector) then use the following code to bring that view forward.
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"STORYBOARDNAME" bundle:nil];
UIViewController *vc = [mainStoryboard instantiateViewControllerWithIdentifier:#"VIEWCONTROLLERIDENTIFIER"];
[self presentModalViewController:vc animated:YES];
I have a case where I want to present a view controller from the main part of the app, one with settings & help & so on. To do this, I want it to be within a nav controller, sort of a little plug in module we can call from a UIBarButtonItem.
Now, this can be to/in the current storyboard, or to another, it doesn't matter.
I want to do it this way, because I loathe the potential of segue line spaghetti all over my storyboard.
Here's how to do it.
- (IBAction)displaySettings:(id)sender
{
LOG_SELECTOR() // google that for extra goodness
// FYI, this can be done using a different storyboard like so.
/*
NSString * storyboardName = #"MainStoryboard_iPhone"; // possibly use device idiom?
UIStoryboard * storyboard = [UIStoryboard storyboardWithName:storyboardName bundle:nil];
*/
// To push a new set of scenes with a new Navigation Controller, it is done like this:
UINavigationController *settingsNC = [self.storyboard instantiateViewControllerWithIdentifier:#"Settings Nav Controller"];
OBSettingsUIViewController *settingsVC = [self.storyboard instantiateViewControllerWithIdentifier:#"Settings root"];
[settingsNC pushViewController:settingsVC animated:NO];
[settingsNC setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
// Present the view controller;
[self presentViewController:settingsNC animated:YES completion:NULL];
}
In the presented view controllers (or in a subclass of the Navigation Controller), you can have a UIBarButtonItem to then dismiss the whole presented hierarchy of view controllers like so:
- (IBAction)dismissThisVC:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
Hope this helps a bunch of people out. Cheers.
Just call viewcontroller using navigation controller
Write this code in viewcontroller and set viewcontroller in storyboard as set in the image.
ProfileVC *vc = [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"ProfileVC"];
[self.navigationController pushViewController:vc animated:YES];
Call to navigate to other class
UIWindow *window = [[[UIApplication sharedApplication] windows] objectAtIndex:0];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
UINavigationController *navController = (UINavigationController *)window.rootViewController;
DumpFeed *dump = [storyboard instantiateViewControllerWithIdentifier:#"DumpFeed"];
dump.isPushed=YES;
dump.strUserId = appDelegate.strFriendid;
[navController pushViewController:dump animated:YES];
Heres a Swift version of this:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let myVC = storyboard.instantiateViewControllerWithIdentifier("myStoryId")
self.presentViewController(myVC, animated: true, completion: nil)
You should also change your storyboard id like this:
I think that with iOS7 it has become very easy implementing via the storyboard
I'm currently learning about the new features in iOS7 and found this simple solution, but it might have been relevant even in prior versions, I'm not sure.
First u need to connect the presenting VC with the target VC (thats the only connection needed), then within the storyboard's attributes inspector choose the style to be modal, in the identity inspector give your VC a storyboardID and make sure you checked the 'use storyboardID' checkbox,
If its not there yet add this method to your presentingVC:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
YourTargetVC * targetVC =
(YourTargetVC *)segue.destinationViewController;
if(nil != targetVC) {
//Do preparations here
}
}
Now, when you wish to show your targetVC from your presentingVC you can use:
[self performSegueWithIdentifier:(NSString *) sender:(id)];
where the identifier is your viewController's storyboardID, and the sender is the view who triggered the action, this method will invoke the storyboards scene, so the [prepareForSegue: sender:] method will be called allowing u making last modifications before the targetViewController will appear.

Switch between view controllers

I want programatically switch from one view controller to another. I use the following code :
SenderPlayerViewController *myViewController = [[SenderPlayerViewController alloc] init];
[self.navigationController pushViewController:myViewController animated:YES];
but I get a black screen, while I have already put some controls in SenderPlayerViewController.
Are u trying to instantiate with an nib file? If so, you must use initWithNibName:bundle:
SenderPlayerViewController *myViewController = [[SenderPlayerViewController alloc] initWithNibName:#"SenderPlayerViewController" bundle:nil];
Also with a story board it is not enough to call alloc init on a controller class.
It should be something like
UIViewController *viewController = [[UIStoryboard storyboardWithName:#"MainStoryboard" bundle:NULL] instantiateViewControllerWithIdentifier:#"SenderPlayerViewController"];
If you are using a view controller from a storyboard you should use
SenderPlayerViewController *myViewController=[storyboard instantiateViewControllerWithIdentifier:#"TheNameOfYourController"]
instead of alloc init.