我在网上做了一些研究,并没有找到一个简单的方法来做到这一点.我想在这里分享一些我的想法,看看是否有更好的方法来做到这一点.
1,在委托中取消didEnterBakcground中的popovers.似乎不实用,因为我们必须添加所有popovers引用.
2,在当前窗口中递归遍历所有视图,以通过(class = _UIPopoverView)查找弹出视图.这看起来有点hacky和危险.
3,在拥有弹出窗口的每个对象中设置UIApplicationDidEnterBackgroundNotificationgroundNotification并将其关闭.这似乎是合理的,但如果你的应用程序中有数百个弹出窗口,那真的很麻烦.
4,如何添加类别方法说 – (void)dismissWhenAppWillEnterBackground;并注册通知.
或者有更容易的方法吗?
解决方法
基本上类别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