当iPad应用程序进入后台时关闭弹出窗口

6

你好,我正在开发一款iPad应用程序,并被要求在应用程序后台运行时关闭所有的弹出窗口(如果有的话)。

我在网上进行了一些研究,但没有找到一个简单的方法。我想在这里分享一些我的想法,看看是否有更好的方法来解决这个问题。

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

2、递归地遍历当前窗口中的所有视图,通过(class = _UIPopoverView)找到弹出窗口视图。这似乎有点儿巧妙和危险。

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

4、或者增加一个类别方法,例如-(void)dismissWhenAppWillEnterBackground; 并注册通知。

还有更容易的方法吗?


2
为什么你的应用程序会有数百个弹出窗口?只需将活动弹出窗口设置为观察UIApplicationDidEnterBackgroundNotification或willEnterBackground等效,并让它们自行关闭。 - Jessedc
@Jessedc 这是业务需求,需要这些弹出窗口。我只是想看看是否有比这更好的解决方案。谢谢。 - ThinkChris
4个回答

10

这里有一个针对UIPopoverController的即插即用类别,可以实现您所需的功能。

基本上,该类别会交换initWithContentViewController:方法,以便它可以在NSHashTable中跟踪实时UIPopoverController实例(它本身并不保留包含的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

3
我可以给你一个更好的答案,就是在UIPopoverController中添加一个类别方法-(void)dismissWhenAppWillEnterBackground并注册UIApplicationWillEnterBackgroundNotificationgroundNotification

2
编写一个带有一些可选方法的协议:
- (void)appWillEnterBackground;
- (void)appWillBecomeActive;

让你的视图控制器实现它,然后在你的应用程序委托中,访问你的根视图控制器,在应用程序进入后台和变得活跃时检查它是否响应这些方法并调用它们。

你应该能够轻松获取根视图控制器。如果你有一个视图控制器层次结构,则可能需要转发调用。

例如,在appWillEnterBackground中添加你的弹出框退出代码。


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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接