Detect popover dismiss in iOS8 - ios

in my iPad-app I connected a UIButton to another UIViewcontroller by just dragging in Storyboard and chose popover as segue. Everything is working fine, but the user can dismiss the popover by touching just somewhere besides the popover right.
How can I detect that the popover has dismissed in iOS8? In iOS7 I could just use the UIPopoverDelegate -popoverDidDidmiss...
But this is not working anymore!? I googled a lot but could not find any solution.

You put your
-(void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
in the UIViewController where the start UIButton is ? (not in another popover UIViewcontroller ?)
That work well for me with iOS 8.1...
You have to delegate to the initial UIViewController for that.

I assume you set the delegate properly, but do you retain the popover, i.e. assign it to a strong property? In ios7 if you didn't retain the popover you would get exception: '[UIPopoverController dealloc] reached while popover is still visible.' In ios8 this is not longer the case, so you get the working popover and you can dismiss it, but the delegate methods are not called anymore.
(Frankly speaking, I'm not sure why this is so. I'd suppose that at least "should dismiss popover" should be called anyway).

You should probably use UIPopoverControllerDelegate and the method
popoverControllerDidDismissPopover:
to accomplish what you need.

in iOS8, it is using the UIViewController's UIPopoverPresentationController to present the popover. (Optionally you still can use back the old UIPopoverController to build the popover manually.
If you are using storyboard on iOS8, you can set the UIViewController's popoverPresentationController delegate to handle the followings:
popoverPresentationControllerShouldDismissPopover:
popoverPresentationControllerDidDismissPopover:

Related

iOS8 - prevent rotation on presenting viewController

We have a MainViewController with a tableView, and it presents a new modalViewController.
The MainViewController is restricted to portrait only, and the modalViewController can rotate.
The problem is in iOS8, that when the modalViewController rotates, the callback method of rotation in iOS8 in MainViewcontroller is called - - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
Thus, the UITableView is getting its data reloaded, which is a behaviour we don't want.
Can we prevent this feature of iOS 8, and not rotate the presenting UIViewController?
So after long days of searching and investigating, I finally came up with a possible solution.
First of all, I can use navigation controller and push the viewController instead of presenting it, but it breaks my code and just isn't so true.
The second thing I can do is not setting constraints. I still can use autolayout, but if I don't set constraints, and let the default constraints to be set, the tableView doesn't get reloaded. of course this is also isn't very smart thing to do, as I have many elements in my viewController.
Finally, I figured out that I can show this "modal" viewController in another UIWindow. I create UIWindow and set the modalViewController as its rootViewController.
I put some example project in git:
https://github.com/OrenRosen/ModalInWindow
Hope it will be helpful.
I did something similar with a navigation controller, that wouldn't rotate unless the top pushed controller does rotate.
In your case check if the main controller is presenting another controller. If it isn't then just reject rotation, otherwise return whatever the presented controller returns for the rotation method.
As for your table view, it shouldn't get reloaded because of rotations.
In iOS 8 the view that rotates when you change the device orientation is the first view added to the UIWindow. So, if you save a reference to it in your presentedController, you can overwrite the shouldAutorotate and supportedInterfaceOrientations values.

How to get reference to UIPopoverController when using adaptive segue?

In my iOS 7 app, I detected if a segue was a popover via this check in prepareForSegue:
if ([segue isKindOfClass:[UIStoryboardPopoverSegue class]])
But now that I am using adaptive segues, the Present as Popover segue is no longer returning true in the above check. This is because segue is no longer a UIStoryboardPopoverSegue, instead it is a UIStoryboardPopoverPresentationSegue. However, one cannot simply add the Presentation word because that's not defined.
What is the appropriate way to detect when the segue is a popover from an adaptive segue, as opposed to a full screen modal presentation?
And, how do you get a reference to the popover for iOS 8? The following is what I'm doing for iOS 7 but again because it's not a UIStoryboardPopoverSegue this will cause a crash.
UIPopoverController *popover = ((UIStoryboardPopoverSegue *)segue).popoverController;
popover.popoverContentSize = CGSizeMake(380, 1000);
There actually was no need to get a reference to the popover for iOS 8. You can access the popoverPresentationController directly in the view controller that's presented. Then use dismissViewControllerAnimated to dismiss the view controller. You can set the popover content size directly in the view controller that's being presented via preferredContentSize. I found I had no need to obtain a reference in prepareForSegue, at least when running on iOS 8. iOS 7 is a different story.
Elaborating on Joey's answer, which led me to what seems the new manner of achieving what we used to do with UIPopoverController.
This code in prepareForSegue:Sender:
UIViewController *destination = segue.destinationViewController;
UIPopoverPresentationController *ppc = destination.popoverPresentationController;
ppc.delegate = self;
is a simple way to successfully set your view controller as delegate of a UIPopoverPresentationController much the same as you are probably used to doing with the old UIPopoverController.
And, of course, while you are at it you'll probably add:
[destination setPreferredContentSize:CGSizeMake(300.00f, 300.00f)];
if you were in the habit of setting UIPopoverController size here as well.
This may not be the most foolproof way to do it but you could check the popoverPresentationController property on your destination view controller. From there you can configure the popover anchor and such.
Check the "Configuring a Popover for Display" section of the UIPopoverPresentationController doc. (Not sure if we're allow to link to them at this point, are we?)
Note too that now we're talking about UIPopover*Presentation*Controllers, not UIPopoverControllers. It's a little confusing...

Dismiss a popover from itself programatically

I'm making a UIPopoverController and displaying it. All is well, content is loading... except I need to dismiss the popover when a button is pressed. The UIPopoverController's delegate is set to self but I don't know how to call a method in the parent view controller.
UIPopoverController has method
- (void)dismissPopoverAnimated:(BOOL)animated
so you can dismiss it directly from itself.
Unless you meant that you want to dismiss popover from its contentViewController, then there is at least dozen of answers regarding that here - for instance similar to this one

Prevent UIActionSheet from dismissing on ipad

I have a universal app that uses a UIActionSheet. The selection is mandatory, which works fine on the iphone, but on iPad it is presented as a popover, so tapping outside of it dismisses it, which I don't want to allow.
I know that there is a delegate method for UIPopoverController I could use, but I don't think I can get access to the UIActionSheet's popover controller to set the delegate etc...
Anyone know how I can do this?
Thanks in advance.
It's possible using undocumented APIs, see
See Accessing UIPopoverController for UIActionSheet on iPad about changing passthroughViews for UIPopoverView which is an undocumented ancestor of UIActionSheet.
Another solution would be to override [UIApplication sendEvent:] and filter the touches coming outside the action sheet.
I recommend you to use a different widget for modal selection. Users don't expect UIActionSheet to be modal, so it would be only confusing to them.

iOS: UIActionsheet (or UIPopoverController view) becomes zombie

I have an UIViewController. Within it the user may launch an UIActionsheet or a popover. If the device rotates, the UIViewController is intentionally released. The problem is that the UIActionsheet / popover lives on and becomes a zombie to haunt me afterward. The user may click a button in the zombie and crash the application. I tried to call [actionsheet dismissWithClickedButtonIndex:0 animated:NO] in dealloc or shouldAutorotateToInterfaceOrientation. No effect. Appreciate any suggestions. Thanks.
I found the solution from this post: [dismiss actionsheet][1]
[1]: iPad crash with UIActionSheet displayed from child view controller. I made a mistake trying to recall the actionsheet by searching through the UIViewController view's subviews or calling the viewWithTag method. Strangely enough, it did return a non-nil object. But using this object to call dismissWithClickedButtonIndex does not work.
The autor of the post suggests using an UIActionSheet pointer and dismiss the actionsheet in viewWillDisapper works. For the above specific application, I found it worked better to dimiss the actionsheet in dealloc.

Resources