iPad: How to close a UIPopoverController by pressing its own "Done" button - uipopovercontroller

My popover has its own "done" button, I want to dismiss my popover by touching this option but still can't figure out how, this is a capture of the app
The code of creation (inside rootview controller named VisitVC)
- (IBAction)showStartEndEvent:(id)sender {
if ([[UIDevice currentDevice].model hasPrefix:#"iPhone"])
[self performSegueWithIdentifier:#"viewSceneStartEndEvent" sender:self];
else
{
//iPad Popover Section
if (!startEndEventPopover || !startEndEventPopover.popoverVisible)
{
StartEndEventVC *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"StartEndEventVC"];
controller.FecInicioDateSE = self.fecInicioDateV;
controller.fecFinDateSE = self.fecFinDateV;
navController = [[UINavigationController alloc]initWithRootViewController:controller];
navController.toolbarHidden = FALSE;
startEndEventPopover = [[UIPopoverController alloc] initWithContentViewController:navController];
[startEndEventPopover presentPopoverFromRect:CGRectMake(400, [sender convertPoint:[sender bounds].origin toView:self.view].y, 300, 400) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
else{
[startEndEventPopover dismissPopoverAnimated:YES];
startEndEventPopover = nil;
}
}
}
now the "done" button code inside popover controller (StartEndEventVC)
- (IBAction)saveChanges:(id)sender {
if (fechaInValida) {
[[[UIAlertView alloc]initWithTitle:#"Notificación" message:#"La fecha de inicio debe ser anterior a la fecha de finalización" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil] show];
return;
}
[self comparaFechaInicio];
[self.startDateLabel removeObserver:self forKeyPath:#"text"];
[self.endDateLabel removeObserver:self forKeyPath:#"text"];
[CurrentParentViewController setFecFinDateV:self.fecFinDateSE];
[CurrentParentViewController setFecInicioDateV:self.fecInicioDateSE];
if ([[UIDevice currentDevice].model hasPrefix:#"iPhone"])
[self.navigationController popViewControllerAnimated:YES];
else{
[self.navigationController dismissViewControllerAnimated:YES completion:^{}];
}
}
the code key for dismissing the popover is on the block:
if ([[UIDevice currentDevice].model hasPrefix:#"iPhone"])
[self.navigationController popViewControllerAnimated:YES];
else{
**[self.navigationController dismissViewControllerAnimated:YES completion:^{}];**
}
but don't know how, any ideas???

To dismiss a popover you have to send dismissPopoverAnimated: to your popover controller. To accomplish that, you should keep a reference to your popover, and then from the view controller you are presenting in your popover controller inform the view controller you are presenting your popover from about the button press, and at this point you call dismissPopoverAnimated:. You can use delegation or a block to inform about the button press.

I did it!!! with delegate, all I have to do is to implement a delegate to my popover's class (startEndEvent.h)
#class StartEndEventVC;
#protocol StartEndEventVCDelegate
#optional -(void)startEndEventsVC:(StartEndEventVC *)sender;
#end
#interface StartEndEventVC : UITableViewController
#property (strong, nonatomic) id <StartEndEventVCDelegate> delegate;
#end
inside my save data method I implemented the delegate like so...
- (IBAction)saveChanges:(id)sender {
if (fechaInValida) {
[[[UIAlertView alloc]initWithTitle:#"Notificación" message:#"La fecha de inicio debe ser anterior a la fecha de finalización" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil] show];
return;
}
[self comparaFechaInicio];
if ([[UIDevice currentDevice].model hasPrefix:#"iPhone"]){
[self.startDateLabel removeObserver:self forKeyPath:#"text"];
[self.endDateLabel removeObserver:self forKeyPath:#"text"];
[CurrentParentViewController setFecFinDateV:self.fecFinDateSE];
[CurrentParentViewController setFecInicioDateV:self.fecInicioDateSE];
[self.navigationController popViewControllerAnimated:YES];
}
else{
[self.delegate startEndEventsVC:self];
}
}
and finally on my rootViewController's class (VisitVC.m) I adopted my custom StartEndEventVCDelegate
#interface VisitVC ()<StartEndEventVCDelegate>
...
#end
I set my popover's delegate and implement the popover's delegate method
- (IBAction)showStartEndEvent:(id)sender {
if ([[UIDevice currentDevice].model hasPrefix:#"iPhone"])
[self performSegueWithIdentifier:#"viewSceneStartEndEvent" sender:self];
else
{
//iPad Popover Section
if (!startEndEventPopover || !startEndEventPopover.popoverVisible)
{
StartEndEventVC *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"StartEndEventVC"];
controller.FecInicioDateSE = self.fecInicioDateV;
controller.fecFinDateSE = self.fecFinDateV;
controller.delegate = self;
navController = [[UINavigationController alloc]initWithRootViewController:controller];
navController.toolbarHidden = FALSE;
startEndEventPopover = [[UIPopoverController alloc] initWithContentViewController:navController];
[startEndEventPopover presentPopoverFromRect:CGRectMake(400, [sender convertPoint:[sender bounds].origin toView:self.view].y, 300, 400) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
else{
[startEndEventPopover dismissPopoverAnimated:YES];
startEndEventPopover = nil;
}
}
}
-(void)startEndEventsVC:(StartEndEventVC *)sender{
[startEndEventPopover dismissPopoverAnimated:YES];
}
there it is... if you have a smaller solution is welcome but it works just fine :)

Related

I am unable to dismiss a GameCenter leaderboard/view

GameCenter is able to open. However, when the "done" button is pressed on the top right corner to dismiss GameCenter, GameCenter still remains open. How do I close GameCenter?
Below is my code:
- (void) presentLeaderboards
{
GKGameCenterViewController *leaderboardController = [[GKGameCenterViewController alloc] init];
if (leaderboardController != nil)
{
leaderboardController.viewState = GKGameCenterViewControllerStateLeaderboards;
UIViewController *vc = self.view.window.rootViewController;
[vc presentViewController: leaderboardController animated: YES completion:nil];
}
}
- (void)gameCenterViewControllerDidFinish:(GKGameCenterViewController *)viewController
{
NSLog(#"Close");
UIViewController *vc = self.view.window.rootViewController;
[vc dismissViewControllerAnimated:YES completion:nil];
}
You never set a delegate for your GKGameCenterViewController so your gameCenterViewControllerDidFinish: method is never called. You should have found this yourself through a little debugging.
Call dismissViewControllerAnimated on viewController.
Your code should be more like:
- (void) presentLeaderboards
{
GKGameCenterViewController *leaderboardController = [[GKGameCenterViewController alloc] init];
if (leaderboardController != nil)
{
leaderboardController.gameCenterDelegate = self;
leaderboardController.viewState = GKGameCenterViewControllerStateLeaderboards;
UIViewController *vc = self.view.window.rootViewController;
[vc presentViewController: leaderboardController animated: YES completion:nil];
}
}
- (void)gameCenterViewControllerDidFinish:(GKGameCenterViewController *)viewController
{
NSLog(#"Close");
[viewController dismissViewControllerAnimated:YES completion:nil];
}
Adding the line:
leaderboardController.gameCenterDelegate = self;
may lead to a new error. If so, you need to add the following to the .m before the #implementation line.
#interface MyViewControllerNameHere () <GKGameCenterControllerDelegate>
#end
If you already have the class extension, just add the GKGameCenterControllerDelegate part.

dismissing a view controller and presenting another viewController

In my application, I have 4 UIViewcontrollers - A, B, C and D.
From my UIViewController A, UIVIewControllers B or C or D can be presented. Suppose, from A, i have presented B. Then, on B, there is are two UIButtons, clicking on which, i need to dismiss B and Present C or dismiss B and Present D. This is happening successfully, but first, after dismissing B, the screen of A comes, and then it goes to C or D.
Here's what i did:
On Button Press On B, the action is:
{
UINavigationController *controller = (UINavigationController *)self.parentViewController;
NSLog(#"%#",[controller parentViewController]);
UITabBarController *tabBarReference = (UITabBarController *)[controller parentViewController];
HomePageViewController *presController = (HomePageViewController *)tabBarReference.presentingViewController;
[presController dismissTabControllerWithHandlerWithSenderAtIndex:1];
}
In A, i have these methods:
-(void)dismissTabControllerWithHandlerWithSenderAtIndex:(NSInteger)index
{
if(index == 0)
{
[self dismissViewControllerAnimated:NO completion:^{
[self aboutButtonPressed:self];
}];
}
else
{
[self dismissViewControllerAnimated:NO completion:^{
[self settingsButtonPressed:self];
}];
}
}
Here's the method i am calling..
- (IBAction)settingsButtonPressed:(id)sender
{
[self.contactUsView setHidden:YES];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSString *deviceType = [prefs objectForKey:#"DeviceType"];
NSString *iOSType = [prefs objectForKey:#"iOSType"];
if([iOSType isEqualToString:#"iOS7"])
{
if([deviceType isEqualToString:#"iPad"])
{
SettingsViewController *settingsPage = [[SettingsViewController alloc] initWithNibName:#"SettingsViewController_iPad" bundle:NULL];
settingsPage.modalTransitionStyle = UIModalTransitionStylePartialCurl;
[self presentViewController:settingsPage animated:YES completion:NULL];
}
else
{
SettingsViewController *settingsPage = [[SettingsViewController alloc] initWithNibName:#"SettingsViewController" bundle:NULL];
settingsPage.modalTransitionStyle = UIModalTransitionStylePartialCurl;
[self presentViewController:settingsPage animated:YES completion:NULL];
}
}
else
{
if([deviceType isEqualToString:#"iPad"])
{
SettingsViewController *settingsPage = [[SettingsViewController alloc] initWithNibName:#"SettingsViewController_iPad_iOS6" bundle:NULL];
settingsPage.modalTransitionStyle = UIModalTransitionStylePartialCurl;
[self presentViewController:settingsPage animated:YES completion:NULL];
}
else
{
SettingsViewController *settingsPage = [[SettingsViewController alloc] initWithNibName:#"SettingsViewController_iOS6" bundle:NULL];
settingsPage.modalTransitionStyle = UIModalTransitionStylePartialCurl;
[self presentViewController:settingsPage animated:YES completion:NULL];
}
}
}
Ok here goes:-
Suppose viewcontroller A is the base & it presents either view controllers B or C.
Implement delegate/notifications where the view controller B or C has to be dismissed.
After sending the delegate or posting the notification, dismiss the current view controller without animation, i.e animation:NO.
This notification that was posted needs to be heard in view controller A.
Here you present the next view controller.
EDIT:-
-(void)dismissTabControllerWithHandlerWithSenderAtIndex:(NSInteger)index
{
if(index == 0)
{
[self dismissViewControllerAnimated:NO completion:nil];
[self aboutButtonPressed:self];
}
else
{
[self dismissViewControllerAnimated:NO completion:nil];
[self settingsButtonPressed:self];
}
}

SKStoreProductViewController cancel button crash or not working

I have implemented a delegate for the SKStoreProductViewController.
I add that view controller into the key window's view controller.
I have also implemented a dismiss view controller code in the delegate function.
The question seems to be answer in this question.
Modal App Store won't dismiss
Yet, this problem still persist in my situation.
Display function
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
NSString *appURL = [NSString stringWithFormat:#"itms-apps://itunes.apple.com/%#/app/id%#",
[[NSLocale preferredLanguages] objectAtIndex:0], applicationID];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:appURL]];
} else {
NSDictionary* dict = [NSDictionary dictionaryWithObject:applicationID forKey:SKStoreProductParameterITunesItemIdentifier];
SKStoreProductViewController *viewCont = [[SKStoreProductViewController alloc] init];
viewCont.delegate = self;
[viewCont loadProductWithParameters:dict completionBlock:^(BOOL result, NSError *error)
{
UIViewController* viewController = [UIApplication sharedApplication].keyWindow.rootViewController;
if (viewController)
{ [viewController presentViewController:viewCont animated:YES completion:nil]; }
}];
}
Delegate Function
- (void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController
{
if (viewController)
{ [viewController dismissViewControllerAnimated:YES completion:nil]; }
}
The problem is that you must implement
- (void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController
{
if (viewController)
{ [self dismissViewControllerAnimated:YES completion:nil]; }
}
inside the delegate class. If you implement it inside the class whose delegate is presenting the SKStoreProductViewController, it will not work because SKStoreProductViewController will try to call productViewControllerDidFinish: within it's delegate, which isn't implementing that method.
Let me show an example:
#implementation MainViewController
- (void)presentSecondViewController
{
SecondViewController *secondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
[secondViewController setDelegate:self];
[self presentViewController:secondViewController animated:YES completion:nil];
}
- (void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController
{
if (viewController)
{ [self dismissViewControllerAnimated:YES completion:nil]; }
}
#end
#implementation SecondViewController {
id delegate <SKStoreProductViewControllerDelegate>;
}
- (void)setDelegate:(id)delegate
{
_delegate = delegate;
}
- (void)callStoreProductViewController
{
SKStoreProductViewController *viewCont = [[SKStoreProductViewController alloc] init];
viewCont.delegate = _delegate;
[viewCont loadProductWithParameters:dict completionBlock:^(BOOL result, NSError *error)
{
UIViewController* viewController = [UIApplication sharedApplication].keyWindow.rootViewController;
if (viewController)
{ [_delegate presentViewController:viewCont animated:YES completion:nil]; }
}];
}
#end
So, if I did understand your problem well, you must implement productViewControllerDidFinish: inside your viewController class, as it is the one who is presentig the SKStoreProductViewController.
Hope this helps!
Please try in Delegate function, replace all lines with:
[self dismissViewControllerAnimated:YES completion:nil];
Where does this code reside? You set the delegate to the instance where this code is written, but you are adding the SKStoreProductViewController to the root view.
Have you tried adding the store to self?
[self presentViewController:storeController animated:YES completion:nil];
Thanks for the delegate function. It isn't obvious in the documentation.

Can't resize height contentSizeForViewInPopover of UIViewController in side UINavigationController of UIPopover

I use UINavigationController inside UIPopoverController
-(void)showEditMenuFrom:(UIButton *)button{
if (self.popover) {
[self.popover dismissPopoverAnimated:YES];
self.popover = nil;
}
else {
EditMenuViewController *editMenuViewController = [[EditMenuViewController alloc] initWithNibName:#"EditMenuViewController" bundle:nil];
UINavigationController *actionsNavigationController = [[UINavigationController alloc] initWithRootViewController:editMenuViewController];
actionsNavigationController.delegate = self;
// switch for iPhone and iPad.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
self.popover = [[UIPopoverController alloc] initWithContentViewController:actionsNavigationController];
self.popover.delegate = self;
// CGRect presentFrame = CGRectMake(button.frame.origin.x-43, button.frame.origin.y-10, button.frame.size.width, button.frame.size.height);
[self.popover presentPopoverFromRect:button.frame inView:button permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
} else {
[self presentViewController:actionsNavigationController animated:YES completion:^{
NSLog(#"Activity complete");
}];
}
}
}
And I try to resize view inside UIPopover when navigate and these are result:
Root view:
2.Push to other VC
3.Pop back:
You can see the height of root VC can't change back to origin size.
I try to set contentSizeForViewInPopover in viewDidAppear, viewDidLoad and in UINavigationControllerDelegate but no methods work
-(void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
NSLog(#"Show VIEW %#",viewController);
if ([viewController isKindOfClass:[EditMenuViewController class]]) {
viewController.contentSizeForViewInPopover = CGSizeMake(160.0, 160.0);
} else {
viewController.contentSizeForViewInPopover = CGSizeMake(320.0, 320.0);
}
}
How to solve this problem? Thanks!
I end up my question for someone meet this solution:
First, you need to declare a #property inside the VC which pop back on stack
#property (nonatomic, strong) UIPopoverController *popover;
Then assign it to UIPopoverController in main code
self.popover = [[UIPopoverController alloc] initWithContentViewController:actionsNavigationController];
self.popover.delegate = self;
editMenuViewController.popover = self.popover;
And Finally, setting the size in viewWillAppear of VC you want to resize
-(void)viewWillAppear:(BOOL)animated
{
[self.popover setPopoverContentSize:CGSizeMake(160,160)];
self.contentSizeForViewInPopover = CGSizeMake(160,160);
[super viewWillAppear:animated];
}
Try with bellow example miht be usefull:-
-(void)showEditMenuFrom:(UIButton *)button{
if (self.popover) {
[self.popover dismissPopoverAnimated:YES];
self.popover = nil;
}
else {
EditMenuViewController *editMenuViewController = [[EditMenuViewController alloc] initWithNibName:#"EditMenuViewController" bundle:nil];
UINavigationController *actionsNavigationController = [[UINavigationController alloc] initWithRootViewController:editMenuViewController];
actionsNavigationController.delegate = self;
// switch for iPhone and iPad.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
self.popover = [[UIPopoverController alloc] initWithContentViewController:actionsNavigationController];
self.popover.delegate = self;
popover.popoverContentSize =CGSizeMake(250,200); //Addint this line for setContentsize
[self.popover presentPopoverFromRect:button.frame inView:button permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
} else {
[self presentViewController:actionsNavigationController animated:YES completion:^{
NSLog(#"Activity complete");
}];
}
}
}
In EditMenuViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//self.clearsSelectionOnViewWillAppear = NO; //this work if superclass is UITableviewcontroller
self.contentSizeForViewInPopover = CGSizeMake(200,100);
}
-(void)viewWillDisappear:(BOOL)animated
{
self.contentSizeForViewInPopover = CGSizeMake(250,200);
[super viewWillDisappear:YES];
}
ADD
Check some useful similar to your issue:-
Animate popoverContentsize when pushing navigation view controller in popover on iPad
UIPopoverController automatically resizing to max height on pushViewController
push a new tableViewController in a uipopovercontroller causes the popover to be resized
Popover with embedded navigation controller doesn't respect size on back nav

Displaying WEPopover from UIButton instead of UIBarButtonItem

I am using WEPopover in my app to pop up a popover controller containg some buttons,it works when i put wepopover controller action in tabbarIteam but i need to get popover when i click UIButton.How to do this this is my barbuttonitem code for displaying popover.
-(IBAction)_clickbtnAccount:(id)sender
{
if (!self.popoverController)
{
UIViewController *contentViewController = [[pageAccount alloc]initWithNibName:#"pageAccount" bundle:nil];
self.popoverController = [[[popoverClass alloc] initWithContentViewController:contentViewController] autorelease];
self.popoverController.delegate = self;
self.popoverController.passthroughViews = [NSArray arrayWithObject:self.navigationController.navigationBar];
[self.popoverController presentPopoverFromBarButtonItem:sender
permittedArrowDirections:(UIPopoverArrowDirectionUp|UIPopoverArrowDirectionDown)
animated:YES];
[contentViewController release];
}
else
{
[self.popoverController dismissPopoverAnimated:YES];
self.popoverController = nil;
}
}
-(IBAction)_clickbtnAccount:(id)sender
{
if (!self.popoverController)
{
UIButton *senderButton = (UIButton *)sender;
[self.popoverController presentPopoverFromRect:[senderButton frame]
inView:#"pageAccount"
permittedArrowDirections:(UIPopoverArrowDirectionUp|UIPopoverArrowDirectionDown)
animated:YES];
}
else
{
[self.popoverController dismissPopoverAnimated:YES];
self.popoverController = nil;
}
}
So you don't want to display a WEPopoverfrom an UIBarButtonItem but from an UIButton, right?!
Just use
- (void)presentPopoverFromRect:(CGRect)rect
inView:(UIView *)view
permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections
animated:(BOOL)animated;
instead of
- (void)presentPopoverFromBarButtonItem:(UIBarButtonItem *)item
permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections
animated:(BOOL)animated;
and pass in the rect of your UIButton.
Taking your code as an example:
-(IBAction)_clickbtnAccount:(id)sender
{
if (!self.popoverController) {
UIViewController *contentViewController = [[pageAccount alloc]initWithNibName:#"pageAccount" bundle:nil];
self.popoverController = [[[popoverClass alloc] initWithContentViewController:contentViewController] autorelease];
self.popoverController.delegate = self;
self.popoverController.passthroughViews = [NSArray arrayWithObject:self.navigationController.navigationBar];
UIButton *senderButton = (UIButton *)sender;
[self.popoverController presentPopoverFromRect:[senderButton frame]
inView:self.view
permittedArrowDirections:(UIPopoverArrowDirectionUp|UIPopoverArrowDirectionDown)
animated:YES];
[contentViewController release];
} else {
[self.popoverController dismissPopoverAnimated:YES];
self.popoverController = nil;
}
}
WEPopover is basically used to show multiple options inside a popover with much control using UITableview.
This is how i use WEPopOver to show popup on a button click
-(void)showPopOver:(id)sender{
if (self.popoverController) {
[self.popoverController dismissPopoverAnimated:YES];
self.popoverController = nil;
}
PopOverTable *contentViewController = [[PopOverTable alloc] initWithStyle:UITableViewStylePlain];
contentViewController.delegatePopoverItemSelectedDelegate=self;
rectForPopover = [self.view convertRect:btn.bounds fromView:btn];
self.popoverController = [[[popoverClass alloc] initWithContentViewController:contentViewController] autorelease];
if ([self.popoverController respondsToSelector:#selector(setContainerViewProperties:)]) {
[self.popoverController setContainerViewProperties:[self improvedContainerViewProperties]];
}
self.popoverController.delegate = self;
[self.popoverController presentPopoverFromRect:rectForPopover
inView: self.view
permittedArrowDirections:(UIPopoverArrowDirectionAny)
animated:YES];
}
With the accepted solution I get rotation issues for the WEPopover under iOS 7: Basically it was pointing to a custom button in the UIBarButtonItem on the left of the navigation bar but on rotation the pop up moves to the right side of the screen and stays there on further rotations.

Resources