当iPad应用程序进入后台时,关闭popover

时间:2013-07-05 00:55:35

标签: ios ipad uipopovercontroller popover

您好我正在使用iPad应用程序并且当应用程序进入后台时需要关闭所有popovers (如果有的话)。

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

1,在委托中解除 didEnterBakcground 中的弹出窗口。似乎不实用,因为我们必须添加所有popovers引用。

2,在当前窗口中以递归方式所有视图查找(class = _UIPopoverView)的弹出窗口视图。这看起来有点黑客和危险。

3,在拥有弹出窗口的每个对象中设置 UIApplicationDidEnterBackgroundNotificationgroundNotification并将其关闭。这似乎是合理的,但如果你的应用程序中有数百个弹出窗口,那真的很麻烦。

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

或者有更容易的方法吗?

4 个答案:

答案 0 :(得分:10)

以下是UIPopoverController上的一个付款类别,可以满足您的要求。

基本上类别会调动initWithContentViewController:,以便它可以跟踪UIPopoverController中的实时NSHashTable实例(它本身并不包含所包含的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

答案 1 :(得分:3)

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

答案 2 :(得分:2)

使用几种可选方法编写协议:

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

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

例如,在appWillEnterBackground中添加您的popover解雇代码。

答案 3 :(得分:2)

  1. 为应用程序中的所有视图控制器创建一个uiviewcontroller基类。
  2. 添加一个数组,其中包含对特定viewcontroller
  3. 中弹出视图的引用
  4. 维护对当前viewcontroller iin app delegate的引用。
  5. 当应用程序进入后台时,获取当前的viewcontroller并遍历popover数组并关闭所有的popovers。