In my initial view controller, I have the following code:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showSearch"]) {
[segue.destinationViewController setInitialLocation:self.locationManager.location];
}
}
When a button is pressed in the initial vc, the segue labeled "showSearch" is activated and the second view controller is loaded with the data inside. The second view controller is a map, and the data are pins at certain locations, collected from the Parse database. My question is, is there anyway to avoid the initial view controller? In other words, I don't want to load up my app, then have to press a button to get to the map view. I want the map view to load first, with the pins already on the map.
You can change your initial view controller by going to storyboard, selecting the view controller you want to become the new initial view controller, going to the attributes inspector, and checking "is initial view controller."
In first view controller's viewDidLoad call the button method which is responsible for the segue to second view controller.
Solved the problem by adding this to the viewDidLoad.
[self performSegueWithIdentifier:#"showSearch" sender:self];
Not ideal, but it works. Although it works fine on my phone, it doesn't seem to work perfectly on the xcode simulator.
If you have a lot of database related code in an initial VC, but that VC isn't handling an UI, maybe you could change your program so that the database code was separated out into its own class. Then the map VC can be your initial VC and it can call your database class to get the data.
So, maybe you have a location manager class with a getInitialLocations method that the map VC can call to load itself with data. Just guessing based on your description.
Related
This question already has answers here:
Passing data between view controllers
(45 answers)
Closed 8 years ago.
I am having trouble passing data back between 2 viewControllers. They are linked with a segue and I am trying to link the data generated in the 2nd viewController and use it in the 1st viewController.
The way it works is the user starts at the 1st viewController and navigates to the 2nd viewController which contains multiple settings to choose. When they navigate back to the 1st viewController, I want the data to be passed. With prepareForSegue, it is very simple, but what should I do? Is there a method such as prepareForSegue that works in reverse (i.e going back to the main viewController)? I have tried to use unwindSegues but I am not sure if this is the appropriate method to be using. Can anyone tell me the correct way of setting this up? Or is there a different method I should use? Any help regarding what I should do would be greatly appreciated.
The best way to go about this is to use a delegate. See the articles here and here to learn about delegation. This answer and this one may also help.
You don't have to do anything like that. The unwind method looks something like that:
- (IBAction)unwindToPackerView:(UIStoryboardSegue*)sender
You have access to segue and you can have reference to your source view controller (2 view controller)
- (IBAction)unwindToPackerView:(UIStoryboardSegue*)sender {
// you can check is this right segue if you have more than one:
if ([sender.identifier isEqualToString:#"SegueIdentifier"]) {
CustomViewController *vc2 = sender.sourceViewController;
// get the data from source view controller
}
}
Note that you should add this method to the first view controller.
// Extended
If you want to call unwind segue after button (bar button, etc.) clicked just control drag from the button to the unwind icon (exit icon) in storyboard.
But if you want to run unwind segue programatically (after some action happened, like swipe gesture) you should connect your unwind segue to the view controller (File owner). Simple control drag from view controller (file owner) to the unwind icon in storyboard and choose appropriate segue.
In the code when the action (for example swipe) happened call:
- (void)performSegueWithIdentifier:(NSString *)identifier sender:(id)sender
I have an app with several views. Taking into consideration the large main view, called MyView1, it is controlled by MyView1Controller. Within MyView1, there is a button that causes a modal segue to another view, whose controller is also MyView1Controller. This modal view has a couple UILabels, and a button that terminate the modal view, bringing the user back to MainView1.
Here is the problem... Let's say in my modal view there is a UILabel called sampleLabel. While in MyView1, a button is pressed, which executes the code:
sampleLabel.text = #"changed";
Since the UILabel named sampleLabel is not on screen for MyView1, and instead is part of the modal view from MyView1, nothing happens. However, when I click on the button to view the modal view from MyView1, the UILabel hasn't changed.
This is even more puzzling since the main MyView1 and the modal view that segues off of MyView1 are controlled by the same view controller, MyView1Controller.
Can someone please tell me how I can make code that executes during the user's interaction with MyView1 change things in the modal view, so that when they press the button and segue to the modal view, the UILabel's have already been changed?
Thanks!
First of all, Apple recommends (and it makes life a lot easier) to have one view controller for each view. So you should have a second view controller. In the second view controller you would have a property called sampleLabel. In the first view controller you could use different methods to set the sampleLabel.text. I would probably create a separate sampleLabelText property in the first view controller (could be an NSString *) and set it to the text you want when the user presses a button. Then in your
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
you would get your second view controller and set its property like this:
SecondViewController *svc = [segue destinationViewController];
svc.sampleLabel.text = self.sampleLabelText;
That's it. Hope this helps.
So I have had a similar issue that I resolved through 'delegation' but not through a segue schema. Here is a link to the stackoverflow question and my answer. Delegation
Hopefully this gets you going in the right path. Instead of modally presenting a view, I push a new viewcontroller onto a navigation stack but the same answer should apply, hopefully :P
I decided to give the use of storyboards a go in my current iPhone app. I am facing a bit of a problem. I really need to reuse my UIViewController instances.
What do I mean by that? Well, for example I have a table view controller. When I tap a cell, another view controller is loaded from the storyboard and pushed onto the navigation controller stack. This all works well, but it takes about half a second to a second each time this view controller is loaded. Before I was using story boards I simply solved this problem by caching the created instance so the second time you tap a cell the view controller can be immediately shown.
By caching the created instance I mean something like this:
if (!cachedInstance) {
cachedInstance = [MyViewController new];
}
[self.navigationController pushViewController:cachedInstance];
Does anyone know how to accomplish this using the storyboard? Thanks in advance.
If you are using segues, you will need to create custom segues in order to use a cached view controller like you did before. Otherwise, the typical "push" segue will create a new instance of the view controller for segue.destinationViewController. If you write a custom UIStoryboardSegue class and use custom segues you can override initWithIdentifier:source:destination: and put your cached view controller in for the destinationViewController, and then override perform to use the classic pushViewController call.
That is how you handle the segue if you are really intent on using them. I would just skip it though, unless you really want the fancy arrows to lay everything out on your storyboard. If you skip it you can just instantiate the view controllers into the cache and then push them on just like you did before.
If your question is more about locating a view controller inside a storyboard then you can use:
UIViewController *vc = [[UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil] instantiateViewControllerWithIdentifier:#"Some View Controller"];
Then you can save that to your cache and push it like you did in your example code.
Hope that helps.
I've set up a really simple project using storyboards including two views as shown here: http://i.stack.imgur.com/iRx21.png. The navigation can be done by either selecting a cell in the custom table view or hitting the back button labelled with "<<". Everything works fine except the following:
when I switch between the views, every time an instantiation happens. The profiling shows an increasing number of view objects. I would like to keep only one of each view and instantiation should be happen only once. What am I doing wrong? (I'm using ARC.)
Thanks in advance!
You should not link your back button to the parent view controller. This is what causes the new instantiation.
The way to go is to embed the table view into UINavigationController (in IB, choose Editor -> Imbed In -> Navigation Controller. Then change your segue to a Push segue. You can of course hide the navigation bar etc. to make things look exactly as you like. Then, link the back button to the controller with an IBAction and in the handler do a simple
[self.navigationController popViewControllerAnimated:YES];
This would be the appropriate logic of what you are doing. Of course, you can also push the web view modally and then handle the button click with
[self dismissModalViewControllerAnimated:YES];
I have a view controller that controls the switching between views. I would like one of the views to signal the view controller to switch to another view (and can't figure out how I can do this.)
To be more clear (hopefully): My view controller inserts a subview. That subview has a UITableView. I'd like, when you select a row in the UITableView, to remove the current subview and then switch to a different sub-view. Of course, I'd prefer the view controller to continue to keep track of which subview is loaded.
Does this make sense? (I'm still pretty green with Objective-C.)
Is there a way to send the view controller a message from the sub-view (that the view controller created)? Is there another way to accomplish this?
Thanks a bunch for the help... and I'd be happy to clarify if needed.
You might look into setting up a UINavigationController. Use the 2 UIViewControllers to control the individual views, and use the Navigation Controller to switch between the 2 views. From the UITableView, you can simply implement the method -
(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
Use this method to alloc the new view controller that you want to display
Then call the Navigation controller to push the new view controller onto the stack -
[self.navigationController pushViewController:controllerName animated:YES]
Finally, release the view controller that has disappeared.
This way the navigation controller keeps track of who is loaded, and can implement convenience functions like animating the transition. Also make sure to lookup the UITableViewController subclass - it is a subclass of UIViewController, but it provides some convenience functions for dealing with tables, like knowing when the user selects a particular row, and allows for the standard edit functions of most iOS apps.