6

嗨,我正在开发一个 iPad 应用程序,并且需要在应用程序进入后台时关闭所有弹出窗口(如果有)。

我在网上做了一些研究,并没有找到一个简单的方法来做到这一点。我想在这里分享一些我的想法,看看是否有更好的方法来做到这一点。

1,在delegate中关闭didEnterBakcground中的popovers。似乎不切实际,因为我们必须添加所有弹出框引用。

2,递归遍历当前窗口中的所有视图以找到弹出视图(class = _UIPopoverView)。这似乎有点hacky和危险。

3、在每个拥有弹出框的对象中设置UIApplicationDidEnterBackgroundNotificationgroundNotification并关闭它们。这似乎是合理的,但如果您的应用中有数百个弹出框,则确实很麻烦。

4,添加一个类别方法如何说 -(void)dismissWhenAppWillEnterBackground; 并注册通知。

或者有更简单的方法吗?

4

4 回答 4

10

这是一个插入类别UIPopoverController,可以满足您的要求。

基本上,类别 swizzlesinitWithContentViewController:以便它可以跟踪UIPopoverControllera 中的活动实例NSHashTable(它本身并不保持包含的 UIPopoverControllers 活动,因为它保持对它们的弱引用。)它还监视UIApplicationDidEnterBackgroundNotification,并且当它到达时它迭代活动 UIPopoverControllers 的集合和驳回任何正在显示的内容。

扩展它以实现 Apple 的“不允许同时显示两个弹出窗口”规则可能会很好。

我不是生产应用程序中方法调配的忠实粉丝,但这似乎很安全。

没有特别的使用说明。只需在您的项目中包含该类别并正常使用您的 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
于 2013-08-02T23:11:41.073 回答
3

我可能有一个更好的答案,即向 UIPopoverController 添加一个类别方法-(void)dismissWhenAppWillEnterBackground并注册UIApplicationWillEnterBackgroundNotificationgroundNotification

于 2013-07-29T23:50:21.567 回答
2

编写一个带有几个可选方法的协议:

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

让您的视图控制器实现它,然后在您的应用程序委托中,访问您的根视图控制器,检查它是否响应这些方法并在应用程序进入后台并变为活动状态时调用它们。您应该能够轻松获得根视图控制器。如果您有视图控制器的层次结构,您可能需要转发呼叫。

appWillEnterBackground例如,在 中添加您的弹出框解除代码。

于 2013-07-29T08:21:39.140 回答
2
  1. 为应用程序中的所有视图控制器创建一个 uiviewcontroller 基类。
  2. 添加一个数组,其中包含对特定视图控制器中弹出视图的引用
  3. 在 app delegate 中维护对当前 viewcontroller 的引用。
  4. 当应用程序进入后台时,获取当前视图控制器并遍历弹出框数组并关闭所有弹出框。
于 2013-08-04T17:21:49.937 回答