I'm initialising my UIPopoverPresentationController from code:
ChoseOptionsViewController *contentController = [[ChoseOptionsViewController alloc] init];
contentController.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController *copvc = contentController.popoverPresentationController;
copvc.permittedArrowDirections = UIPopoverArrowDirectionAny;
copvc.sourceView = sender;
copvc.sourceRect = sender.bounds;
contentController.preferredContentSize = CGSizeMake(200, 200);
[self presentViewController:contentController animated:YES completion:nil];
And all I'm getting is an empty 200x200 view, although I've created a ViewController in storyboard, assigned ChoseOptionsViewController class to it and dragged some UI elements.
Tell me please, how can I get my view from storyboard when initialising a popover from code.
Thanks in advance.
When you make a view controller in the storyboard, you should create an instance of it with instantiateViewControllerWithIdentifier:, not alloc init.
ChoseOptionsViewController *contentController = [self.storyboard instantiateViewControllerWithIdentifier:#"Whatever"];
Make sure your controller in the storyboard has its identifier set to the same string you pass to the method.
Related
I want to present a view controller as an popup in iPhone from a UIBarButtonItem
I have written the following piece of code on the action of the button.
-(IBAction)showAvailableCategory:(UIButton *)sender
{
CategoryPopup *categoryPopupViewController = [[CategoryPopup alloc]init];
UIPopoverPresentationController *popOverCat = categoryPopupViewController.popoverPresentationController;
categoryPopupViewController.preferredContentSize = CGSizeMake(138, 122);
popOverCat.delegate = self;
popOverCat.sourceView = sender;
popOverCat.sourceRect = sender.bounds;
popOverCat.permittedArrowDirections = UIPopoverArrowDirectionAny;
[self presentViewController:categoryPopupViewController animated:YES completion:nil];
}
I have made my CategoryPopup as freeform in the xib and also I am implementing the below delegate method
-(UIModalPresentationStyle) adaptivePresentationStyleForPresentationController: (UIPresentationController * ) controller
{
return UIModalPresentationNone;
}
But it does not come up as popup rather it comes fullscreen, is there a workaround?
You forgot just one setting, add it right after categoryPopupViewController's initialization:
categoryPopupViewController.modalPresentationStyle = UIModalPresentationPopover;
I have added subview in a UIViewController and I want a new UIViewController Should be loaded on click of button.
Challenge is I am not able to use button in new UIViewController.
Code which I have write:
DetailsOfDayViewController *aViewController =[[DetailsOfDayViewController alloc] initWithNibName:#"DetailsOfDayViewController" bundle:nil];
aViewController.dateParsing = dateparsing;
[self addSubview:aViewController.view];
This will fix your issue. This is happening because your view controller is being deallocated when you don't have any strong pointers on it.
DetailsOfDayViewController *aViewController =[[DetailsOfDayViewController alloc] initWithNibName:#"DetailsOfDayViewController" bundle:nil];
aViewController.dateParsing = dateparsing;
[self addChildViewController:aViewController];
[self addSubview:aViewController.view];
Another fix will be connecting this view controller to a property:
#property(nonatomic,strong) DetailsOfDayViewController *aViewController;
And change your code like this:
self.aViewController = [[DetailsOfDayViewController alloc] initWithNibName:#"DetailsOfDayViewController" bundle:nil];
self.aViewController.dateParsing = dateparsing;
[self addSubview:self.aViewController.view];
For showing another controller you can following options
1. Add SubView
newViewControllerObj.view.frame = oldViewControllerObj(self).view.frame
[oldViewControllerObj(self).view.newViewControllerObj.view];
2. Present
[oldViewControllerObj(self) presentViewController: newViewControllerObj animated:YES completion:nil];
3. Push using Navigation (For this you already have to set navigation controller as root controller)
[oldViewControllerObj(self).navigationController pushViewController:newViewControllerObj animated:YES];
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 trying to change the preferred content size of a UIPopOverController from inside the childViewController.
Firstly I present PopOverViewController this way
DateViewController *dateView = [[DatePickerViewController alloc] initWithNibName:#"DateViewController" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc]initWithRootViewController:dateView];
m_tableCell = (NotesCell *)[m_tableView cellForRowAtIndexPath:indexPath];
popViewController = [[UIPopoverController alloc] initWithContentViewController:navController];
popViewController.backgroundColor = [[AppManager instance].themeManager navigationBarColor];
popViewController.delegate = self;
//the rectangle here is the frame of the object that presents the popover,
//in this case, the UIButton…
CGRect popRect = CGRectMake(m_tableCell.customView.frame.origin.x,
m_tableCell.customView.frame.origin.y,
m_tableCell.customView.frame.size.width,
m_tableCell.customView.frame.size.height);
[popViewController presentPopoverFromRect:popRect
inView:m_tableCell
permittedArrowDirections:UIPopoverArrowDirectionRight
animated:YES];
So inside my childViewController i.e (DateViewController), I have button which when toggled will call a function
- (void)toggleButton
{
if(small)
{
self.presentingViewController.presentedViewController.preferredContentSize = CGSizeMake(320,485);
}
else
{
self.presentingViewController.presentedViewController.preferredContentSize = CGSizeMake(320,320);
}
}
This is working fine, but as we know that UIPopOverViewController has arrow, so when I resize the popOverView, the arrow also animates up and down, which I dont want. I cannot show this in image, so please excuse me for that.
Need help
Ranjit.
First of all the code you posted won't work, because in else statement you assign CGSizeMake giving only one value while constructing it.
Secondly you can define in which directions you allow for that arrow by specifying popoverArrowDirection property
That simple example but that don't work;
I have ViewController where inside on NavigationConroller, then I want to add new ViewConroller with its self navigation controller.
In main viewController:
CustomViewController *vc = [[CustomViewController alloc] init];
NewNavigationVC *nav = [[NewNavigationVC alloc] initWithRootViewController:vc];
[self presentViewController:nav animated:NO completion:nil];
Two controllers has a background color clear, but still black color.
Navigation bar I can do clear, but not a view.
UPDATE:
if i change self.window.backroundColor to red for example, that work but not clear
UPDATE 2:
[self addChildViewController:vc];
[self.view addSubview:vc.view];
[vc didMoveToParentViewController:self];
and when I want to dealloc vc
[vc willMoveToParentViewController:nil];
[vc.view removeFromSuperview];
[vc removeFromParentViewController];
All work ok without navigation controller
A viewController's view's backgroundColor can't be clear (as in showing the previous viewController's view on the stack). Pushing or presenting a viewController will put the new viewController on the stack and hide the previous viewController completely.
If you want a clear backgroundColor on the view, you will need to either:
1) set the viewController as a childViewController of the previous viewController - then animate the transition yourself.
Or
2) transplant the viewController logic into the previous viewController and have a new uiview act as that view (you also need to animated the transition yourself).
The solution is as follows. For clear example we use tableViewController:
UITableViewController *modalVC = [UITableViewController new];
UINavigationController *modalNVC = [[UINavigationController alloc] initWithRootViewController:modalVC];
UIViewController *mainVC = [UIViewController new];
UINavigationController *mainNVC = [[UINavigationController alloc] initWithRootViewController:mainVC];
modalVC.view.backgroundColor = UIColor.clearColor;
mainVC.view.backgroundColor = UIColor.redColor;
mainNVC.modalPresentationStyle = UIModalPresentationCurrentContext;
[mainNVC presentViewController:modalNVC animated:YES completion:NULL];
The key feature is that you have to set modalPresentationStyle of presentingViewController to UIModalPresentationCurrentContext.
It works fine BUT without slide animation. You will get result immediately.
But you can still use "blood hack" to retain visual animation by successive presenting, dismissing and presenting again:
modalVC.view.backgroundColor = UIColor.clearColor;
mainVC.view.backgroundColor = UIColor.redColor;
[mainNVC presentViewController:modalNVC animated:YES completion:^{
[modalNVC dismissViewControllerAnimated:NO completion:^{
mainNVC.modalPresentationStyle = UIModalPresentationCurrentContext;
[mainNVC presentViewController:modalNVC animated:NO completion:NULL];
}];
}];
You basically need to tell the navigation controller to:
navigation.modalPresentationStyle = .overCurrentContext
In other words:
A presentation style where the content is displayed over another view controller’s content.
and that's it.
You can also make sure that:
navigation.view.backgroundColor = .clear