Is it possible to pass data between storyboards in objective-c with segue when the application is not made from a master detail template?
The only examples I have seen is the one with master detail views.
Yes, it is. You could implement prepareForSegue:sender: in the viewController you are segueing from, like so:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"MySegue"]) {
MyOtherViewController *destination = (MyOtherViewController *)segue.destinationViewController;
destination.someProperty = self.someOtherProperty;
}
}
This will get called before your segue is performed, giving you a hook into the viewController you are segueing to.
Edit:
I didn't realise your ViewControllers were in different Storyboard. This question has already been pretty much answered, here: https://stackoverflow.com/a/9610972/1716763
You wouldn't actually be using a segue though, you would do things programatically and either push your second view controller onto the navigation stack, or present it modally.
I've adapted some of the code from #Inafziger's answer to fit your example:
UIStoryboard *secondStoryBoard = [UIStoryboard storyboardWithName:#"secondStoryBoard" bundle:nil];
MyOtherViewController *myViewController = (MyOtherViewController *)[secondStoryBoard instantiateViewControllerWithIdentifier:#"myOtherViewController"];
myViewController.someProperty = self.someOtherProperty;
[self.navigationController pushViewController:myViewController animated:YES];
Related
I have a UIViewController that contains a UITableView. The table view contains a custom UITableViewCell. The custom cell was built in interface builder and has a nib. In my main storyboard, I dragged a segue from the custom table view cell to the destination view controller. I set up the bare bones essentials in prepareForSegue, set a break point, but it never gets called.
I'm not that accustomed to using a UITableView in a view controller. I usually use a UITableViewController, but requirements dictate using the table view in a view controller. My initial assumptions is that most methods of doing things would be nearly identical, but I'm finding that not to be the case.
I tried setting the segue from the view controller itself and using didSelectRowAtIndexPath, and though it worked, the transition to the destination view controller was jerky.
Can anyone suggest what I might be missing in order to cause the prepareForSegue method to fire?
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
GaugeViewController *destination = [segue destinationViewController];
[destination setGaugeID:#"1"];
}
Thanks!
You need to refer to the identity of the segue in the Storyboard, something like this:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
GaugeViewController *destination = segue.destinationViewController;
if([segue.identifier isEqualToString:#"yourSegue"]) {
NSLog(#"prepareForSegue called");
[destination setGaugeID:#"1"];
}else {
// do something else
}
}
Also don't forget to set the Identifier in the Storyboard.
Remember that push segues are used with Navigation Controllers and a modal segue can be dragged from view controller to view controller.
I'm making a simple word game in Objective-C for iOS, and I started out by selecting "Single View Application", so I have one myProgramViewController.xib file, and one each of myProgramViewController.h and myProgramViewController.m. I just now realized that I would like to have a main menu type thing that loads first, and allows the user to select the length of the word, difficulty, stuff like that, and a "Go!" or "Start!" button. How can I add this menu view? I would prefer that the user could not go back to it (for now), so I'd rather not use the navigation bar.
Context in comments above.
When a segue happens, you can pass any data from one ViewController to another. What I would do in your case is set up with a storyboard, have the menu controller be the initial view controller, then have the game screen be a modal segue from that.
In the - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender (on your MenuViewController) you can get segue.destinationViewController and set the data on it.
Example:
MenuViewController ---- playGameSegue ----> GameViewController
In MenuViewController.m
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
GameViewController * destination = (GameViewController*) sender.destinationViewController;
destination.anyPropertyYou'veDefinedInGameViewController.h = DATA;
destination.otherProperty = DATA;
}
You can present the view modally. Say you have a view called MainMenu, which has a .xib,.h and .m file.
In your myProgramViewController.m file, you can call the code
MainMenu *mainMenu = [[MainMenu alloc] initWithNibName:#"MainMenu" bundle:nil];
[self presentModalViewController:mainMenu animated:YES];
Then in your MainMenu.m file, once the user has made their selections, call:
[self dismissModalViewControllerAnimated:YES];
Hey guys i`m trying to present a modal view controller inside an application with a tab bar controller. The problem is, every time the new view is presented, it on top of my tab bar.
I need to keep my tab bar even when the view is presented. Like google maps application does with his toolbar at the bottom of the screen.
How can i do that?
Thank you
By default, a modal view controller is meant to take up the entire screen (on an iPhone/iPod, at least). Because of this, it covers whatever you have on screen at the time.
A view controller presented via modal segue is meant to live on its own. If you want to keep your Navigation and TabBar, then just use a push segue to present the new ViewController. Remember to use this kind of segue, your presenting controller needs to be part of a UINavigationController already.
Use this to push a ViewController. If it is a UINavigationController it will push its linked RootViewController by itsself.
Create a viewController to push: (Using Storyboard)
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"LoginViewController"];
or (Using Code/Nibs)
LoginViewController *viewController = [[LoginViewController alloc] init]; //initWithNibNamed in case you are using nibs.
//in case you want to start a new Navigation: UINavigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
and push with:
[self.navigationController pushViewController:vc animated:true];
Also, if you are using Storyboards for the segues you can use this to do all the stuff. Remember to set the segue identifier.
[self performSegueWithIdentifier:#"pushLoginViewController" sender:self]; //Segue needs to exist and to be linked with the performing controller. Only use this if you need to trigger the segue with coder rather than an interface object.
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"pushLiftDetail"]) {
[[segue.destinationViewController someMethod:]];
segue.destinationViewController.someProperty = x;
}
}
I think you'll need to add a UITabBar to the modal view and implement/duplicate the buttons and functionality that your main bar has. The essence of a modal window is it has total control until it is dismissed.
You might try putting your UITabBarController into a NavBarController, but I'm not certain that this will work.
UITabBarController -> NavBarController -> Modal View
I need to perform a segue from my storyboard. The method to call in that case is -[UIViewController performSegueWithIdentifier:sender:]. This method relies on the storyboard property of UIViewController to find the storyboard (and therefore the segue).
However, the storyboard property is not set when the UIViewController was not created from the storyboard. And since it's read-only, I can't set it programmatically where I load my storyboard.
So the question is: how to perform a segue from a storyboard that has been loaded programmatically?
If it's not possible, it's perhaps because my architecture is incorrect. Here is the use case:
The app is a legacy tabbar application where each of the 8 tabs has its own NIB file. Many of the 8 tabs are rather complex, and can benefit a lot from storyboards, especially prototype table cells and static tables. So I want to evolve the app to use storyboards.
However, one humongous storyboard doesn't seem a good idea: it would prevent incremental changes to the app, it would be unwieldy, it would make it difficult for the team members to work on their tab independently.
The right level of modularity seems to let the UITabBarController have its own specific storyboard. This makes it possible for each tab to evolve at its own pace and makes it easier for each developers to work on their tab with few source control conflicts.
My approach so far is the main nib file to contain the UITabBarController and each of its main daughter view controllers. The daughter view controllers load their storyboard from their viewDidLoad method. And from there, they can't perform their segue.
The alternative would be for the daughter view controllers to be created from their storyboards, but then how can I hook them up to the UITabBarController? And where do I programmatically load the storyboards?
Thanks for any suggestion.
make a reference on the segue and save the pointer value in a singleton class. Then using the pointer reference saved in the singleton class, access the segue wherever you like and load it. Here is a sample code in which i am loading a segue view from a single storyboard class but each view has separate view controllers .h and .m files that have appropiate connections. (i used formal protocol, hence the line shareVC.delegate = self; is there .
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue isKindOfClass:[UIStoryboardPopoverSegue class]]) {
if (self.currentPopover != nil) {
[_currentPopover dismissPopoverAnimated:YES];
self.currentPopover = nil;
}
UIStoryboardPopoverSegue *popSegue = (UIStoryboardPopoverSegue *)segue;
self.currentPopover = popSegue.popoverController;
}
if ([segue.identifier compare:#"ShareModal"] == NSOrderedSame) {
//the share controller is being presented modally, probably iphone
UINavigationController *shareNavController = segue.destinationViewController;
myViewController *shareVC = (myViewController *)[shareNavController topViewController];
shareVC.delegate = self;
} else if ([segue.identifier compare:#"SharePopover"] == NSOrderedSame) {
FollowersViewController *followerVC = segue.destinationViewController;
followerVC.delegate = self;
} else if ([segue.identifier compare:#"StartScreenSegue"] == NSOrderedSame) {
UINavigationController *startNavController = segue.destinationViewController;
StartViewController *startVC = (StartViewController *)startNavController.topViewController;
startVC.delegate = self;
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationOpenUrlNotification object:nil];
}
}
Hope this helps:)
I'm writing a storyboard-based iPhone app and working on state restoration. When performing the segues normally, I want to have them animate, but when I'm restoring several levels of a navigation hierarchy, I only want the last segue to animate. Other than setting up two sets of segues—one set that uses a normal push segue, and another that uses a custom non-animating push segue—is there any way to achieve what I'm trying to do?
It's possible to directly manipulate the view controller stack, independently of the application's segues or storyboards.
You can use this technique to restore a deep stack of view controllers, and perform / animate just a single segue to the top view controller. (You will likely need to create a specific push segue for this purpose.)
For example, to restore a two view controller stack, you could do the following. In this example, it's assumed that some action on an existing view controller leads to the state restore, but you can just as easily perform it from your App Delegate.
[self performSegueWithIdentifier:#"Page2Express" sender:self];
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"Page2Express"])
{
// Get any state data you need to from Core Data
CoreDataType *valuePulledFromCoreData = // ...
// Set up the page 2 view controller as you normally would
Page2ViewController *page2ViewController = segue.destinationViewController;
page2ViewController.instanceVariable = valuePulledFromCoreData;
// Create a loose, page 1 view controller and set it up as required
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:nil];
Page1ViewController *page1ViewController = [storyboard instantiateViewControllerWithIdentifier:#"Page1ViewController"]; // Ensure you have this identifier set up in your storyboard
page1ViewController.instanceVariable = valuePulledFromCoreData;
// Add the page 1 view controller to the top of the navigation stack (to be later obscured in the segue by the page 2 view controller)
NSMutableArray *viewControllers = [[self navigationController].viewControllers mutableCopy];
[viewControllers addObject:page1ViewController];
[self navigationController].viewControllers = viewControllers;
}
}
If, instead, you prefer to have no animations, then it's easier still. You can restore state solely by manipulating the view controller stack (and without using any segues) from - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions and - (void)applicationWillEnterForeground:(UIApplication *)application.
Either way will work seamlessly and in tandem with your existing storyboard(s) and segues.