Prevent UIActionSheet from dismissing on ipad - ios

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.

Related

UIContextMenuInteraction : How to Dismiss Manually?

When a UIContextMenuInteraction/UITargetedPreview is visible, is it possible to manually dismiss it? For example, when the app goes to the background, I would like to dismiss it manually.
https://kylebashour.com/posts/context-menu-guide
I was interested in the same thing, and calling UIViewController.dismiss(animated:completion:) on the source view controller dismisses it as it would a modally presented controller.
UIContextMenuInteraction has a method which is called dismissMenu.
I believe this is what you would rather call when in need to hide a menu, because calling dismiss(animated:completion:) could lead to unwanted behaviour if you have another modally presented controller and you are not sure if the menu is active.
Moreover, starting from iOS 13.2 you can get access to contextMenuInteraction as a property of a UICollectionView and call dismissMenu.
contextMenuInteraction is also available as a property for a UITableView starting from iOS 14.0
It becomes quite complicated when your minimal iOS version is 13.0 and you need somehow to dismiss a menu for a cell in a collectionView. This is a bump in the road I am currently having trouble with. I believe the only appropriate way is to create, save and provide a custom PreviewViewController in this method:
collectionView(collectionView: contextMenuConfigurationForItemAt: point:) -> UIContextMenuConfiguration?
When having access to your custom PreviewViewController, you can call dismiss(animated:completion:) method on it whenever you want.

Prevent dismissing modal WKInterfaceController

Is there a way to prevent the user from dismissing a modal controller?
I think it is pretty common to want to "block" the main Watch App interface while asking the user to open the iPhone counterpart or to perform some action there.
My current solution is to present again the controller when it gets dismissed but its clunky.
There's a somewhat kludgy way to get around this issue using reloadRootControllers. When you call reloadRootControllers(withNamesAndContexts:) with the name of a WKInterfaceController that you've named in your storyboard, it has a similar effect to presenting that controller modally. However, since it's now the root controller, it doesn't have a cancel button. I don't really like this, but it does get the job done.
Note this method is deprecated since watchOS 4.
Apple Documentation on reloadRootControllers(withNamesAndContexts:)
The trick is to make the modal screen fullscreen and change the inset top value for your main group.
You can't prevent a modal interface controller from being dismissed, as the system automatically dismisses it when the title is tapped.
Since your code isn't asked if it should happen, but only knows that it is happening, there's no way to intercept or cancel that action. The WKInterfaceController documentation briefly touches on this.
When the user taps the title string, WatchKit automatically dismisses the modal interface without taking any further actions.
What can you do?
While you don't know when the Cancel title is tapped, there is a hack which "hides" the Cancel title.
This may confuse users who might wonder how to dismiss the modal, or mislead others into thinking the modal couldn't be dismissed.
What does the HIG recommend?
Circumventing a Human Interface Guideline would likely degrade the entire user experience.
The top-left corner of the modal sheet is reserved for the Close button, which dismisses the interface.
Some users might be frustrated or annoyed if
there is no apparent way to cancel, or
the modal presents itself again after repeatedly being cancelled.
Since the user expects to be able to dismiss the modal, perhaps you could allow them to do just that, then simply display some form of reminder in the presenting interface controller (to log in, or enable permissions).

Detect popover dismiss in iOS8

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:

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.

Present UISplitViewPopover programmatically

I was wondering if there was a sort of simple way to (when the device is in the correct Portrait orientation), to programmatically display the RootViewController in the UIPopoverController of the UISplitViewController.
You have the UIBarButtonItem that the split view gave you in it's delegate callback. You can use that one:
[barItem.target performSelector:barItem.action withObject:barItem];
Its a hack, but works. Please file a request at http://bugreport.apple.com for a better solution.

Resources