it-swarm.com.de

Referenz auf die oberste Ansicht/Fenster in der iOS-Anwendung abrufen

Ich erstelle ein wiederverwendbares Framework zum Anzeigen von Benachrichtigungen in einer iOS-Anwendung. Ich möchte, dass die Benachrichtigungsansichten über alles andere in der Anwendung hinzugefügt werden, wie eine UIAlertView. Wenn ich den Manager initiiere, der auf NSNotification-Ereignisse wartet und Ansichten als Antwort hinzufügt, muss ich einen Verweis auf die oberste Ansicht in der Anwendung abrufen. Das habe ich im Moment:

_topView = [[[[UIApplication sharedApplication] keyWindow] subviews] lastObject];

Würde dies für jede iOS-Anwendung funktionieren oder ist es eine sicherere/bessere Möglichkeit, die Draufsicht zu erhalten?

95
typeoneerror

Normalerweise erhalten Sie die Ansicht von oben, es kann jedoch nicht garantiert werden, dass es für den Benutzer sichtbar ist. Es könnte sich außerhalb des Bildschirms befinden, ein Alpha von 0,0 haben oder beispielsweise die Größe 0x0 haben.

Es kann auch sein, dass das keyWindow keine Unteransichten hat. Sie sollten dies wahrscheinlich zuerst testen. Das wäre ungewöhnlich, aber nicht unmöglich.

UIWindow ist eine Unterklasse von UIView. Wenn Sie also sicherstellen möchten, dass Ihre Benachrichtigung für den Benutzer sichtbar ist, können Sie sie mithilfe von addSubview: direkt zum keyWindow hinzufügen. Die Ansicht wird am häufigsten angezeigt. Ich bin mir nicht sicher, ob Sie dies tun möchten. (Aufgrund Ihrer Frage scheint es, als ob Sie das bereits wissen.)

36
Kris Markel

Wann immer ich etwas Overlay über allem anderen anzeigen möchte, füge ich es einfach direkt über dem Anwendungsfenster hinzu:

[[[UIApplication sharedApplication] keyWindow] addSubview:someView]
108
samvermette

Das Problem besteht aus zwei Teilen: Oberes Fenster, Draufsicht im oberen Fenster.

Alle vorhandenen Antworten verfehlten den oberen Fensterteil. [[UIApplication sharedApplication] keyWindow] ist jedoch nicht garantiert das oberste Fenster.

  1. Oberes Fenster. Es ist sehr unwahrscheinlich, dass es zwei Fenster mit derselben windowLevel-Koexistenz für eine App gibt, sodass wir alle Fenster nach windowLevel sortieren und das oberste Fenster erhalten können.

    UIWindow *topWindow = [[[UIApplication sharedApplication].windows sortedArrayUsingComparator:^NSComparisonResult(UIWindow *win1, UIWindow *win2) {
        return win1.windowLevel - win2.windowLevel;
    }] lastObject];
    
  2. Draufsicht auf das obere Fenster. Nur um vollständig zu sein. Wie bereits in der Frage dargelegt:

    UIView *topView = [[topWindow subviews] lastObject];
    
45
an0

Tatsächlich kann es mehr als ein UIWindow in Ihrer Anwendung geben. Wenn zum Beispiel eine Tastatur angezeigt wird, enthält [[UIApplication sharedApplication] windows] mindestens zwei Fenster (Ihr Schlüsselfenster und das Tastaturfenster).

Wenn Sie also möchten, dass Ihre Sicht auf beiden erscheint, müssen Sie Folgendes tun:

[[[[UIApplication sharedApplication] windows] lastObject] addSubview:view];

(Angenommen, lastObject enthält das Fenster mit der höchsten windowLevel-Priorität).

11
lorean

Ich bleibe bei der Frage, wie der Titel sagt, und nicht der Diskussion. Welche Ansicht ist an jedem Punkt oben sichtbar? 

@implementation UIView (Extra)

- (UIView *)findTopMostViewForPoint:(CGPoint)point
{
    for(int i = self.subviews.count - 1; i >= 0; i--)
    {
        UIView *subview = [self.subviews objectAtIndex:i];
        if(!subview.hidden && CGRectContainsPoint(subview.frame, point))
        {
            CGPoint pointConverted = [self convertPoint:point toView:subview];
            return [subview findTopMostViewForPoint:pointConverted];
        }
    }

    return self;
}

- (UIWindow *)topmostWindow
{
    UIWindow *topWindow = [[[UIApplication sharedApplication].windows sortedArrayUsingComparator:^NSComparisonResult(UIWindow *win1, UIWindow *win2) {
        return win1.windowLevel - win2.windowLevel;
    }] lastObject];
    return topWindow;
}

@end

Kann direkt mit jedem UIWindow als Empfänger oder jedem UIView als Empfänger verwendet werden.

3
hfossli

Wenn Ihre Anwendung nur im Hochformat funktioniert, ist dies ausreichend:

[[[UIApplication sharedApplication] keyWindow] addSubview:yourView]

Ihre Ansicht wird nicht über Tastatur und Statusleiste angezeigt.

Wenn Sie eine oberste Ansicht erhalten möchten, die sich über der Tastatur oder der Statusleiste befindet, oder Sie möchten, dass die oberste Ansicht bei Geräten korrekt gedreht werden kann, versuchen Sie Folgendes:

https://github.com/HarrisonXi/TopmostView

Es unterstützt iOS7/8/9.

1
Harrison Xi

Wenn Sie eine Ladeansicht hinzufügen (z. B. eine Aktivitätsanzeige), stellen Sie sicher, dass Sie über ein Objekt der UIWindow-Klasse verfügen. Wenn Sie ein Aktionsblatt anzeigen, bevor Sie Ihre Ladeansicht anzeigen, ist die keyWindow die UIActionSheet und nicht UIWindow. Und da das Aktionsblatt verschwindet, verschwindet die Ladeansicht. Oder das hat mir Probleme bereitet.

UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
if (![NSStringFromClass([keyWindow class]) isEqualToString:@"UIWindow"]) {
    // find uiwindow in windows
    NSArray *windows = [UIApplication sharedApplication].windows;
    for (UIWindow *window in windows) {
        if ([NSStringFromClass([window class]) isEqualToString:@"UIWindow"]) {
            keyWindow = window;
            break;
        }
    }
}
1
Miha Hribar

versuche dies

UIWindow *window = [[[UIApplication sharedApplication] windows] lastObject];
0
Chandramani

Verwenden Sie einfach diesen Code, wenn Sie eine Ansicht über alles auf dem Bildschirm hinzufügen möchten.

[[UIApplication sharedApplication].keyWindow addSubView: yourView];
0
handiansom