【问题标题】:Dismiss popover when iPad app goes in background当 iPad 应用程序进入后台时关闭弹出窗口
【发布时间】:2013-07-03 00:23:56
【问题描述】:

您好,我正在开发一款 iPad 应用,并且要求在应用进入后台时关闭所有弹出框(如果有)。

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

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

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

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

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

或者有更简单的方法吗?

【问题讨论】:

  • 为什么您的应用程序中会有数百个弹出窗口?只需将活动弹出框设置为观察 UIApplicationDidEnterBackgroundNotificationgroundNotification 或 willEnterBackground 等效项并让它们自行关闭。
  • @Jessedc 业务需要有这些弹出框。我只是想看看是否有比这更好的解决方案。谢谢。

标签: ios ipad uipopovercontroller popover


【解决方案1】:

这是UIPopoverController 上的一个临时类别,可以满足您的要求。

基本上,类别会调动initWithContentViewController:,以便它可以跟踪NSHashTable 中的实时UIPopoverController 实例(它本身并不保持包含的UIPopoverControllers 活动,因为它保持对它们的弱引用。)它还监视@ 987654325@,当它到达时,它会迭代实时 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

【讨论】:

    【解决方案2】:

    我可能有更好的答案,就是在 UIPopoverController 中添加一个分类方法 -(void)dismissWhenAppWillEnterBackground 并注册 UIApplicationWillEnterBackgroundNotificationgroundNotification

    【讨论】:

      【解决方案3】:

      用几个可选方法编写一个协议:

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

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

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

      【讨论】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-11-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-08-01
          • 1970-01-01
          相关资源
          最近更新 更多