Reject popover when iPad is in the background

Hi, I am working on an iPad application and have received a request to reject all popovers (if any) when the application goes into the background.

I studied online and did not find an easy way to do this. I would like to share some of my ideas here and see if there is a better way to do this.

1, Reject popovers in didEnterBakcground in the delegate. It seems impractical since we have to add a link to popovers.

2, go to all views recursively in the current window to find popover view (class = _UIPopoverView). It seems a bit hacked and dangerous.

3, configure UIApplicationDidEnterBackgroundNotificationgroundNotification in each object that owns popovers and fire them. It seems reasonable, but really troublesome, if your application has hundreds of popovers.

4, How about adding a category method say - (void) rejectWhenAppWillEnterBackground; and register a notification.

Or is there an easier way to do this?

+6
source share
4 answers

Below is the transition category to UIPopoverController that does what you ask.

Basically the swizzles category is initWithContentViewController: so that it can track live instances of the UIPopoverController in NSHashTable (which itself does not hold the live ones contained in the UIPopoverControllers because it keeps weak references to them.) It also tracks for UIApplicationDidEnterBackgroundNotification , and when it does, it repeats living UIPopoverControllers and rejects everything that is displayed.

It might be nice to extend this to implement the “never allow two pop-ups to show right away” rule that Apple has.

I'm not a big fan of the swizzling method in production applications, but it seems pretty safe.

No special instructions to use. Just include the category in your project and usually use UIPopoverControllers.

 #import <objc/runtime.h> @interface UIPopoverController (autodismiss) @end @implementation UIPopoverController (autodismiss) static NSHashTable* ts_popoverHashTable; + (void) load { SEL originalSelector = @selector(initWithContentViewController:); SEL replacementSelector = @selector(ts_initWithContentViewController:); Method originalMethod = class_getInstanceMethod( [UIPopoverController class], originalSelector); Method replacementMethod = class_getInstanceMethod( [UIPopoverController class], replacementSelector); method_exchangeImplementations(originalMethod, replacementMethod); [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector( applicationDidEnterBackgroundNotification: ) name: UIApplicationDidEnterBackgroundNotification object: nil]; } - (id) ts_initWithContentViewController: (UIViewController*) contentViewController { UIPopoverController* pc = [self ts_initWithContentViewController: contentViewController]; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ ts_popoverHashTable = [NSHashTable weakObjectsHashTable]; }); [ts_popoverHashTable addObject: pc]; return pc; } + (void) applicationDidEnterBackgroundNotification: (NSNotification*) n { for ( UIPopoverController* pc in ts_popoverHashTable ) { if ( pc.isPopoverVisible ) { [pc dismissPopoverAnimated: NO]; } } } @end 
+9
source

I may have a better answer that adds a category method - (void), discards the WhenAppWillEnterBackground in the UIPopoverController and registers the UIApplicationWillEnterBackgroundNotificationgroundNotification.

+3
source

Write a protocol with several optional methods:

 - (void)appWillEnterBackground; - (void)appWillBecomeActive; 

Make your view controllers for its implementation, and then in your application’s dellet, go to the root view controller, check if it responds to these methods and call them when the application runs and becomes active. You should be able to easily get the root view controller. If you have a hierarchy of view controllers, you may need to redirect the call.

Add, for example, your termination code to the appWillEnterBackground folder.

+2
source
  • Create a base uiviewcontroller class for all view controllers in the application.
  • Add an array containing links to popover views in a specific view manager
  • Keep a link to the current iont application delegate.
  • When the application enters the background, you get the current view controller and move the popover array and delete all the popovers.
+2
source

Source: https://habr.com/ru/post/948751/


All Articles