I have a UIViewcontroller, with a button. When I press the button it triggers a segue to a popover view (the segue is set through storyboard, not through the codes). When the popover is dismissed (by pressing outside of its bounds), I want the initial view controller to reload. how can I do that?
You can set the delegate of the popover controller in your prepareSegue: method and implement the delegate method popoverControllerDidDismissPopover: which will be called when the popver is dismissed.
You can get the popover controller with UIPopoverController *popover = [(UIStoryboardPopoverSegue *)segue popoverController]
Related
My problem
I have a standard UIViewController. With the press of a button, it loads a form sheet modal view controller. When dismissing this modal view with the press of a UIBarButtonItem I call a method by doing:
ViewController *main = [[ViewController alloc] initWithNibName:nil bundle:nil];
[main updateLabel];
In the method -(void)updateLabel in the main ViewController I'm setting the text of a label, but the label won't change. But I know the function gets called, because if I do a NSLog(#"Method call test); instead of label.text = #"Test" I can see the message in console.
What am I doing wrong? It must be the way I'm calling the method in the main ViewController, because I can easily change the label anywhere else.
What I want to do:
When dismissing a modal view controller, I want a method to be called in the main view controller, and in this case change the text of a label.
Thanks for your help!
You're creating a new instance of ViewController with that code, not getting a pointer to the one you already have.
If ViewController is the controller that presented the modal view, then you can get a pointer to it with,
ViewController *main = self.presentingViewController;
A better way to do this would be to use the delegate pattern.
https://developer.apple.com/library/ios/documentation/general/conceptual/DevPedia-CocoaCore/Delegation.html
The following is a design pattern suggestion
The modal view controller shouldn't know how to dismiss itself, that is the responsibility of the presenting view controller. After all, it could have been presented in many different ways (modally, popover, push navigation). Using the delegate pattern, the modal view controller would tell its delegate that it should be dismissed when the bar button item gets pressed. The delegate, which is the presenting view controller, would then dismiss the modal view and update the label mentioned in your question.
I have a view controller. When I press a button in it, a popover controller with a uitableview shows up. I select a row, which shows another view with some controls in it. When I press a button that says "Save Item", I want it to dismiss the popover. How do I do this?
Here's what I've tried:
Using the delegate and protocol pattern. This hasn't worked since in order to push another view inside my tableview, the whole thing must be embedded in a navigation view controller, so when I segue, it segues to a nav controller, not the tableview which I could set the popover delegate for.
Adding my main view as a member of the view I want to dismiss from. I don't know why this doesn't work.
The Hard Clean Way
There are four view controllers in the story, plus a popover controller. I will call the three view controllers "main view controller", "nav", "vcA", and "vcB". As I understand it, "nav" is the initial content view controller of the popover and has "vcA" as its root view controller.
main view controller -> popover controller -> nav -> vcA -> (later) vcB
When you present the popover from your main view controller, you keep a reference to the popover controller. This is what makes dismissing possible, as you know.
When you create the Save button, you make its target the main view controller and its action a method in the main view controller. You will have to set this up in code; it cannot be configured from a storyboard because you cannot form an action from one scene to another. (You are able to do this because you started out with a reference to nav and vcA when you configured the popover controller initially. Thus you can hand vcA a reference to self, the main view controller. If necessary, you can then pass this reference down the chain from vcA to vcB as vcB is summoned and pushed onto the navigation stack.)
Now the user taps Save, your main view controller's method runs, and it uses its reference to the popover controller to tell it to dismiss.
The Easy Dirty Way
The heck with all that. The main view controller registers for an NSNotification. The Save button posts that NSNotification. Done. :)
The Middle Way
You could set the whole chain up in your storyboard using a popover segue, and do the dismissal through an Unwind segue matched by an unwind method back in the main view controller. I never think of this initially, because I don't like popover segues very much. But it does work.
This is how I solved my problem (sorry for the bad english):
First, Create a property of UIStoryboardPopoverSegue in the VcA and set it from the main view controller.
Nav -> VcA_ViewController
#property (strong, nonatomic) UIStoryboardPopoverSegue *popupSegue;
Then, in the Main View Controller prepareForSegue set the property:
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"your segue from the mainview to the navigation"]) {
UINavigationController *navigationController = (UINavigationController *)c;
VcA_ViewController *vcA = (VRPointOfInterestsFiltersViewController *) navigationController.topViewController;
vcA.popupSegue = (UIStoryboardPopoverSegue*)segue;
} }
Now, from the VcA controller you can have the dismiss button
- (IBAction)dismissPopoup:(id)sender {
[self.popupSegue.popoverController dismissPopoverAnimated:YES]; }
Don't forget to link the popOverSegue from the MainViewController to the NavController.
Hope it helps!
There are two views in a tabbarviewcontroller. And the first tab has its view controller called myViewController which contain its IBOutlet. Pressing the button on the first view will present a view controller. After dismissing the view and back to the tab, the viewWillAppear of myViewController won't be called,but viewWillAppear of tabbarviewcontroller will. I need to reload the information on the first tab. If I use viewWillAppear in tabbarviewcontraller, how do I change the values of these property in myViewController? If anyone has idea ? Thanks.
If you want to call viewWillAppear of the viewController, you can add this to viewWillAppear of the TabBar
for (UIViewController *viewController in tabBarController.viewControllers)
{
[viewController viewWillAppear:YES]
}
I simply want to add a navigation bar (with some nav bar button) on a presented modal controller with storyboard.
Programmatically with XIBs, it looks like that :
SDMapController *mapController = [[SDMapController alloc] initWithNibName:#"SDMapController" bundle:nil];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:mapController];
[self presentModalViewController:navigationController animated:YES];
But I have no idea how to handle it with Storyboard. I guess i have to implement some code on the -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender method but since the destinationController property of segue object is readonly, i don't really know how to do this.
Any idea ?
You have to implement the prepare for segue, only if you want to pass on some data to your presented view controller. Otherwise you can leave it empty. The presenting of the View Controller is from the Interface Builder. You add a navigation controller with it's root view controller and make a segue (ctrl + drag) to the navigation controller. Set the segue type to modal, and give it an ID. You can trigger this segue from code by calling [self perforSegueWithIdentiefier:#"MySegueID"];. If you dragged the segue from a button or a table view cell, it will be triggered automatically when you tap on it, without calling this method. As I said, in the prepareForSegue method, the segue.destinationViewController will bee the presented navigation controller. You can access it's topViewController if you need and pass some data to it.
Here's my problem. With Storyboard's segue I am having a popover segue for a bar button. The UIViewController inside the UIPopoverController requires to load the data from a server. With Storyboards, everytime I close the popover the view is released so whenever the popover appears again it tries to load data again from server. I dont want this behavior. How can I prevent Storyboard from resetting the view controller inside popover controller? Something like what UITabBarController does. UITabBarController calls viewDidLoad for the first time and for the subsequent tab switches viewWillAppear is called.
Segue is designed so. Every time you do segue - view will be loaded.
If you need to store it's data - you should store it outside popover and use this method
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
if ([[segue identifier] isEqualToString:#"your segue identifier"])
{
//get popover
ViewController *vc = [segue destinationViewController];
//Set popover data to vc here
}
which calls before segue, and in this method set data to popover.
If you will use it - don't forget to set Segue identifier in Interface Builder.