So I'm presenting a UIPopoverView like so:
if (self.BStatePopoverViewController == nil) {
RedStatePopoverViewController *settings =
[[RedStatePopoverViewController alloc]
initWithNibName:#"RedState"
bundle:[NSBundle mainBundle]];
UIPopoverController *popover =
[[UIPopoverController alloc] initWithContentViewController:settings];
popover.delegate = self;
self.BStatePopoverViewController = popover;
}
[BStatePopoverViewController setPopoverContentSize:CGSizeMake(320, 445)];
[self.BStatePopoverViewController presentPopoverFromRect:[sender bounds] inView:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
Once the view is loaded in the popover, I have a button which I'd like to use to present a new UIViewController within the popover. I tried just presenting it as a modal view but this changes the parent view as opposed to the one in the popover:
PopupDischargeViewController * dischargeview = [[PopupDischargeViewController alloc] initWithNibName:#"PopupDischargeViewController" bundle:nil];
[self presentModalViewController:dischargeview animated:NO];
Any help as to how I do this would be much appreciated.
Thanks!
To change the view controller the popover should display once it's been initialized use UIPopoverController's method – setContentViewController:animated:
You could also add your RedStatePopoverViewController to a UINavigationController and use its methods – pushViewController:animated: and – popViewControllerAnimated: to navigate between view controllers
Hope this helps!
Related
I am updating an old app to the new adaptive size way of doing things and having difficulty getting a popover with a navigation controller to work.
My goal: I want to be able to open a popover from a button when the app is either compact and regular horizontal. The popover has a tableview and uses a navigation controller to push view controllers when the user touches a row on the table. I can get the popover to open correctly, but I can’t figure out who to make the pushes work.
Here’s the code that opens the popover:
OptionsController *vc = [[OptionsController alloc] initWithNibName:#"OptionsView" bundle:nil];
vc.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController *popover = [vc popoverPresentationController];
popover.delegate = self;
[self presentViewController:vc animated: YES completion: nil];
popover.permittedArrowDirections = UIPopoverArrowDirectionUp; // change as necessary
popover.sourceView = self.view;
CGRect popoverRect = [self.view convertRect:[sender frame] fromView:[sender superview]];
popover.sourceRect = popoverRect;
This code correctly opens a popover in either compact or regular size.
In the OptionsController’s didSelectRowAtIndexPath method, I have this(controllersArray is an array of UIViewControllers, each of which corresponds to a row in the table):
UIViewController *nextController = [self.controllersArray objectAtIndex: [indexPath row]];
[self.navigationController pushViewController:nextController animated:YES];
All this executes, but no push occurs, so the next view never appears.
I clearly am not understanding something about using the UIViewController’s navigationController, or how to install a navigationController to make this work. After three or four days of digging around to try to understand how to make this work, I'd appreciate any insights, or links to documentation about how to do this. Thanks in advance.
Crud - this has a very easy answer. Just took me thinking a different way and digging through Larcerax's comments. Here's how to make this work:
OptionsController *vc = [[OptionsController alloc] initWithStyle:UITableViewStylePlain];
vc.title = #"Options";
UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController: vc];
nc.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController *popover = [nc popoverPresentationController];
popover.delegate = self;
[self presentViewController:nc animated: YES completion: nil];
popover.permittedArrowDirections = UIPopoverArrowDirectionUp; // change as necessary
popover.sourceView = self.view;
CGRect popoverRect = [self.view convertRect:[sender frame] fromView:[sender superview]];
popover.sourceRect = popoverRect;
The difference is that I create the UINavigationController in the usual manner...
UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController: vc];
...set the navigationController's presentation style to popover, then get the popoverPresentationController from the navigationController - before I was doing those two methods on the UIViewController.
nc.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController *popover = [nc popoverPresentationController];
Finally, I present the navigationController:
nc.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController *popover = [nc popoverPresentationController];
This approach presents a popover, in compact and regular horizontal sizes, that contains navigation controller functionality: just what I wanted.
Thanks again to Larcerax whose answer wasn't what I needed, but made me re-think what I was doing in a different way. As usual, StackOverflow comes through.
Here's what you should try. I use about 10-40 navigation controllers per app for the apps I work on and I've had this same sort of issue, I've not used popovers, but I've subclassed the crap out of navigation controllers and view controllers to have encountered your same problem. The thing is that if you do this:
UIViewController * ff = [UIViewController new]
[self presnetViewController:ff ... blah blah blah
There is apparently NO navigation system attached to the modal view controller and therefore you can't navigate to anything else, you can only close the modal and move on. So, this is what I do to resolve this and it works everytime, well it works everytime for UIViewControllers, give it a shot
see the following, it's not for popovers, but the principle is the same:
NSHTermsOfServiceViewController * pvc = [NSHTermsOfServiceViewController new];
UIBarButtonItem * backBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"exit-button"] style:UIBarButtonItemStylePlain target:self action:#selector(backerPressed)];
NSHNavigationController * ssf = [[NSHNavigationController alloc] initWithRootViewController:pvc];
[[pvc navigationItem] setLeftBarButtonItem:backBarButtonItem];
[[self navigationController] presentViewController:ssf animated:true completion:nil];
NSHTermsOfServiceViewController <== is a subclass of another subclass of a UIViewcontroller, it's basically a UIViewController on steroids, that's all
NSHNavigationController is a UINavigationController that is subclassed and pumped up on steroids for animations
The flow is this:
create a viewController
create a new UINavigationController
Set the view controller you created in step 1 as the root view controller of the navigation controller created in step 2
present the NAVIGATION CONTROLLER, not the UIViewController, you can present this navigationController from a view controller like so ..
v
[self presentViewController:ssf animated:true completion:nil];
or you can present it from the current view controller's navigation controller which is what I prefer, like so:
[[self navigationController] presentViewController:ssf animated:true completion:nil];
Your code, modified, the only problem is that I don't know if you can present a UIPopOverViewController by rooting it inside a navigation controller
OptionsController *vc = [[OptionsController alloc] initWithNibName:#"OptionsView" bundle:nil];
UIPopoverPresentationController *popover = [vc popoverPresentationController];
UINavigationController * stuff = [[NSHNavigationController alloc] initWithRootViewController:popover];
stuff.modalPresentationStyle = UIModalPresentationPopover;
stuff.delegate = self;
[self.navigationController presentViewController:stuff animated: YES completion: nil];
popover.permittedArrowDirections = UIPopoverArrowDirectionUp; // change as necessary
popover.sourceView = self.view;
CGRect popoverRect = [self.view convertRect:[sender frame] fromView:[sender superview]];
popover.sourceRect = popoverRect;
Yep, my bad, doesn't work for popover, I just tried it
So, with that said, is it absolutely necessary to use a popover? Why are you using this and now just a UIViewcontroller that you reconfigure to look like a popover and then you have what you need?
Here's this, I just tried it with the Ipad simulator, and it allowed a push, just as it should have.
NSHLoginViewController * pvc = [NSHLoginViewController new];
UINavigationController *navController = [[UINavigationController alloc]initWithRootViewController:pvc];
UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:navController];
UIView * stuff = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 1000, 1000)];
[self.view addSubview:stuff];
[popover presentPopoverFromRect:[[self contentView] nameField].frame inView:stuff permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
this: [[self contentView] nameField].frame is just a uitextfield, nothing special, that's all, and the method above presented the login viewcontroller, when I put in my credentials, I pressed log in and it pusehed the next viewcontroller as it normally would, there's probalby something wrong with the touches being intercepted by your uitableview or whatever, perhaps not, but this method did work for me.
I am looking for a way to present and hide a popover in my application using fade in/out animations. Is it possible?
PopOverDesignController *objPopOverDesignController = [[PopOverDesignController alloc] initWithNibName:#"PopOverDesignController" bundle:nil];
UIPopoverController *popController = [[UIPopoverController alloc] initWithContentViewController:objPopOverDesignController];
popController.delegate = self;
popController.popoverContentSize = objCategoriesViewController.view.frame.size;
[popController presentPopoverFromRect:CGRectMake(130,970,100,100)
inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
[popController dismissPopoverAnimated:YES];
If you want to fadein/fadeout your popover, you need to set the modal transition style to CrossDissolve in your controller with modalTransitionStyle property
Swift
vc.modalTransitionStyle = UIModalTransitionStyle.CrossDissolve
Objective c
vc.modalTransitionStyle.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
Where vc is the view controller that you want to present
I am trying to implement UIPopoverController. I have seen some sample code but still confused on how to connect the popover view controller to storyboard. Help please.
if (!patientPopover) {
UIStoryboard * storyboard = [UIStoryboard storyboardWithName:#"MyStoryboard" bundle:nil];
MyViewController * addPacientController = [storyboard instantiateViewControllerWithIdentifier:#"MyViewController"];
UINavigationController * myNavController = [[UINavigationController alloc] initWithRootViewController:MyViewController];
patientPopover = [[UIPopoverController alloc] initWithContentViewController:myNavController];
patientPopover.delegate = self; // optional
}
[patientPopover presentPopoverFromBarButtonItem:yourInstanceBarButtonItemOrMethodArgumentAttachedToTheBarButtonItem permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
It's good to have your popover in an instance variable so that you avoid allocating it each time you press the button. I am using here presenting the popover from a UIBarButtonItem, but you can also present it from any view, like :
[patientPopover presentPopoverFromRect:yourView.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
You don't need to visually see the actual popover in the storyboard or nib file, because it is only a container. You just need to see what goes inside it, and that is the view controller, and obviously, you can do that.
I have a login view which I want to display in popover. I am doing this from code as below:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:[NSString stringWithFormat:#"MainStoryboard_%#", isIPAD ? #"iPad" : #"iPhone"] bundle:NULL];
UIViewController *navCtrl = [storyboard instantiateViewControllerWithIdentifier:#"LoginViewController"];
UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:navCtrl];
popover = popover;
popover.delegate = self;
popover.popoverBackgroundViewClass = [PopoverBackground class];
self.popover = popover;
[self.popover presentPopoverFromRect:((UIButton *)sender).bounds
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionDown
animated:YES];
But the popover never shows. But the weird thing is viewdidload and viewwillappear for loginview are called. And on again clicking on the view calls the popover delegate method didDismissPopover.
Though it works fine when presented from a popover segue.
I do not want to create a segue because login might be called from different locations and I want to keep this code separate.
Has anyone before faced such issue.
Solved it!!
Turned out I was giving the arrow direction as UIPopoverArrowDirectionDown and the rect to show was not proper. Changed the rect to (100, 500, 10, 10), and voila! Everything is perfect.
I open a popOver with a view(DetailView) in a view(MapView). it works fine.
But in my detail view has a button(feedback).so i want to push the another view(feedbackform)on btton clicked.
I tried but nothing is Happened.
Can i push the view inside the popover?
My code is as follow:
// MapView.m
detailsView *popUp=[[detailsView alloc] initWithNibName:#"detailsView_ipad" bundle:nil];
popView = [[UIPopoverController alloc]initWithContentViewController:popUp];
popView.delegate =self;
[popView setPopoverContentSize:CGSizeMake(600, 500)];
[popView presentPopoverFromRect:control.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
//Detailview.m
-(IBAction)openFeedbackForm:(id)sender {
fbView = [[deatailsFeedback alloc]
initWithNibName:#"deatailsFeedback_ipad" bundle:nil];
[self.navigationController pushViewController:fbView animated:YES];
}
To achieve this your detailsView should be a Navigation controller with a root controller to the original detailsView.
This way when you pop the navigationController, you can perform push from your detailsView and that would only affect the popOver view
detailsView *popUpView=[[detailsView alloc] initWithNibName:#"detailsView_ipad" bundle:nil];
UINavigationController *popUpNavController = [[UINavigationController alloc] initWithRootViewController:popUpView];
popView = [[UIPopoverController alloc]initWithContentViewController:popUpNavController];
popView.delegate =self;
[popView setPopoverContentSize:CGSizeMake(600, 500)];
[popView presentPopoverFromRect:control.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
//Detailview.m
-(IBAction)openFeedbackForm:(id)sender {
fbView = [[deatailsFeedback alloc]
initWithNibName:#"deatailsFeedback_ipad" bundle:nil];
[self.navigationController pushViewController:fbView animated:YES];
}
If I understand your code correctly, openFeedForm IBAction method is in Detailview.m?
Meaning the first part of the code is in a different class than the one at the bottom?
If so, since Detailview itself is not in a navigationController, it will not push anything to its non-existant navigation controller.
What you want to do is have MapView push the new view in its navigationController.
Side note: since you are setting the delegate of the popUp in MapView as (self) the IBAction method should be defined in MapView
(This is assuming my first statement about understanding your code is correct)