嗨,我正在开发一个iPad应用程序,并且要求在应用程序进入后台时关闭所有弹出窗口(如果有的话).
我在网上做了一些研究,并没有找到一个简单的方法来做到这一点.我想在这里分享一些我的想法,看看是否有更好的方法来做到这一点.
1,在委托中取消didEnterBakcground中的popovers.似乎不实用,因为我们必须添加所有popovers引用.
2,在当前窗口中递归遍历所有视图,以通过(class = _UIPopoverView)查找弹出视图.这看起来有点hacky和危险.
3,在拥有弹出窗口的每个对象中设置UIApplicationDidEnterBackgroundNotificationgroundNotification并将其关闭.这似乎是合理的,但如果你的应用程序中有数百个弹出窗口,那真的很麻烦.
4,如何添加类别方法说 – (void)dismissWhenAppWillEnterBackground;并注册通知.
或者有更容易的方法吗?
解决方法
这是UIPopoverController上的一个插件类别,可以满足您的要求.
基本上类别swizzles initWithContentViewController:因此它可以跟踪NSHashTable中的实时UIPopoverController实例(它本身不会保持包含的UIPopoverControllers,因为它保持对它们的弱引用.)它还监视UIApplicationDidEnterBackgroundNotification,当它到达时它会迭代收集现场UIPopoverControllers并解散任何正在显示的内容.
可能很高兴将其扩展到实现Apple所拥有的“永不允许两个popovers立即显示”规则.
我不是生产应用程序中混乱方法的忠实粉丝,但这看起来非常安全.
没有特别的使用说明.只需在项目中包含该类别,即可正常使用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