2013-07-05 7 views
6

Hallo Ich arbeite an einer iPad App und bekam eine Anforderung an alle Popovers (falls vorhanden) zu entlassen, wenn App im Hintergrund geht.Popover zu beenden, wenn iPad App im Hintergrund geht

Ich habe einige Online-Studie und fand keine einfache Möglichkeit, es zu tun. Ich möchte hier meine Idee teilen und sehen, ob es einen besseren Weg dafür gibt.

1, Popover in didEnterBakcground in delegieren. Scheint nicht praktikabel, da wir alle Popovers Referenz hinzufügen müssen.

2, gehen alle Ansichten rekursiv im aktuellen Fenster, um Popover-Ansicht von (class = _UIPopoverView) zu finden. Es scheint ein bisschen hacky und gefährlich.

3, Einrichten UIApplicationDidEnterBackgroundNotificationgroundNotification in jedem Objekt Wer besitzen Popovers und entlassen sie. Dies scheint vernünftig, aber wirklich mühsam, wenn es Hunderte von Popovers in Ihrer App gibt.

4, Wie wäre es mit einer Kategoriemethode say - (void) kündigenWhenAppWillEnterBackground; und Registrierung Benachrichtigung.

Oder gibt es einen einfacheren Weg?

+2

Warum würden Sie Hunderte von Pop-Overs in Ihrer App haben? Legen Sie einfach die aktiven Pop-Overs fest, um UIApplicationDidEnterBackgroundNotificationgroundNotification oder die Entsprechung von willEnterBackground zu beobachten, damit sie sich selbst ablehnen. – Jessedc

+0

@Jessedc Das Geschäft muss diese Popovers haben. Ich möchte nur sehen, ob es eine bessere Lösung als diese gibt. Vielen Dank. – ThinkChris

Antwort

9

Hier ist eine Drop-in-Kategorie auf UIPopoverController, die das tut, was Sie fragen.

Grundsätzlich die Kategorie Swizzles initWithContentViewController: so dass es Live-UIPopoverController-Instanzen in einem NSHashTable verfolgen kann (die selbst die enthaltenen UIPopoverControllers am Leben nicht halten, da sie schwachen Verweis auf sie halten.) Er überwacht auch für UIApplicationDidEnterBackgroundNotification, und wenn dies eintrifft Es iteriert die Sammlung von Live-UIPopoverControllern und gibt alle, die angezeigt werden, frei.

Es könnte schön sein, dies zu erweitern, um die Regel "Nie erlauben zwei Popovers auf einmal zu zeigen" zu implementieren, die Apple hat.

Ich bin kein großer Fan von Methode Swizzling in Produktion Apps, aber das scheint ziemlich sicher.

Keine besonderen Anweisungen zur Verwendung. Fügen Sie einfach die Kategorie in Ihr Projekt ein und verwenden Sie Ihre UIPopoverControllers normalerweise.

#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

schreibt ein Protokoll mit einem paar optionalen Methoden:

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

Machen Sie Ihre Ansicht-Controller, es zu implementieren und dann in AppDelegate, Zugriff auf Ihre Root-View-Controller, ob es auf diese Methoden reagiert und rufen sie, wenn die App in den Hintergrund geht und aktiv wird. Sie sollten in der Lage sein, den Root View-Controller einfach zu erhalten. Wenn Sie eine Hierarchie von Ansichtscontrollern haben, müssen Sie möglicherweise den Anruf weiterleiten.

Fügen Sie Ihren Popover-Kündigungscode beispielsweise in appWillEnterBackground hinzu.

3

Ich habe eine bessere Antwort kann, die eine Kategorie Methode hinzufügen ist - (void) dismissWhenAppWillEnterBackground zu UIPopoverController und UIApplicationWillEnterBackgroundNotificationgroundNotification registrieren.

2
  1. eine Uiviewcontroller Basisklasse erstellen für die alle View-Controller in der Anwendung.
  2. Fügen Sie ein Array hinzu, das die Verweise auf die Popover-Ansichten in dem jeweiligen Viewcontroller enthält
  3. Pflegen Sie einen Verweis auf den aktuellen ViewController in App-Delegaten.
  4. Wenn App im Hintergrund eingeht, den aktuellen Viewcontroller abrufen und das Popover-Array durchlaufen und alle Popovers schließen.