获取对iOS应用程序中最顶层视图/窗口的引用

typ*_*ror 97 objective-c uiview uiwindow ios

我正在创建一个可重用的框架,用于在iOS应用程序中显示通知.我希望将通知视图添加到应用程序中其他所有内容的顶部,有点像UIAlertView.当我初始化侦听NSNotification事件并在响应中添加视图的管理器时,我需要获得对应用程序中最顶层视图的引用.这就是我现在所拥有的:

_topView = [[[[UIApplication sharedApplication] keyWindow] subviews] lastObject];
Run Code Online (Sandbox Code Playgroud)

这适用于任何iOS应用程序,还是更安全/更好的方式来获得顶视图?

sam*_*tte 110

每当我想在其他所有内容上显示一些叠加时,我只需将它直接添加到应用程序窗口的顶部:

[[[UIApplication sharedApplication] keyWindow] addSubview:someView]
Run Code Online (Sandbox Code Playgroud)

  • 只能在纵向工作..你必须关心像这样的轮换等:http://stackoverflow.com/questions/2508630/orientation-in-a-uiview-added-to-a-uiwindow/4960988#4960988 (9认同)
  • 我在 iOS-8 应用程序中收到 `(null)`(故事板问题?)有什么提示吗?谢谢!(注意:`(null)` 在`viewDidLoad` 和`viewWillAppear:` 时间都返回。`viewDidAppear:` 为时已晚。 (2认同)

an0*_*an0 47

问题分为两部分:顶部窗口,顶部窗口顶视图.

所有现有答案都错过了顶部窗口部分.但[[UIApplication sharedApplication] keyWindow]不保证是最佳窗口.

  1. 顶部窗户.windowLevel对于应用程序来说,不太可能存在两个具有相同共存的窗口,因此我们可以对所有窗口进行排序windowLevel并获得最顶层的窗口.

    UIWindow *topWindow = [[[UIApplication sharedApplication].windows sortedArrayUsingComparator:^NSComparisonResult(UIWindow *win1, UIWindow *win2) {
        return win1.windowLevel - win2.windowLevel;
    }] lastObject];
    
    Run Code Online (Sandbox Code Playgroud)
  2. 在顶部窗口的顶视图.只是为了完整.正如问题中已经指出的那样:

    UIView *topView = [[topWindow subviews] lastObject];
    
    Run Code Online (Sandbox Code Playgroud)

  • 一旦UIAlertViews发挥作用,这个解决方案就停止了我的工作 - 它们似乎留下了一个emtpy UIWindow,所以我又回到了`topView = [[[[UIApplication sharedApplication] keyWindow]子视图] lastObject]; (5认同)
  • 如果键盘已启动,则此功能无效.因为那将是最顶层的窗口 (4认同)

Kri*_*kel 36

通常这会给你顶视图,但不保证它对用户可见.它可以在屏幕外,具有0.0的alpha值,或者可以具有0x0的大小.

它也可能是keyWindow没有子视图,所以你应该首先测试它.这不寻常,但并非不可能.

UIWindow是UIView的子类,因此如果您想确保您的通知对用户可见,您可以直接将其添加到keyWindow使用addSubview:,它将立即成为最顶级的视图.我不确定这是不是你想要做的.(根据你的问题,看起来你已经知道了.)


lor*_*ean 11

实际上,您的应用程序中可能有多个UIWindow.例如,如果键盘在屏幕上,[[UIApplication sharedApplication] windows]则将包含至少两个窗口(您的键窗口和键盘窗口).

因此,如果您希望您的视图出现在它们的两个上面,那么您必须执行以下操作:

[[[[UIApplication sharedApplication] windows] lastObject] addSubview:view];
Run Code Online (Sandbox Code Playgroud)

(假设lastObject包含windowLevel优先级最高的窗口).