获取对 iOS 应用程序中最顶层视图/窗口的引用
我正在创建一个可重用的框架,用于在 iOS 应用程序中显示通知。我希望将通知视图添加到应用程序中其他所有内容的顶部,有点像 UIAlertView。当我初始化监听 NSNotification 事件并添加视图作为响应的管理器时,我需要获取对应用程序中最顶层视图的引用。这就是我现在所拥有的:
_topView = [[[[UIApplication sharedApplication] keyWindow] subviews] lastObject];
这适用于任何 iOS 应用程序还是它们是获取顶视图的更安全/更好的方法?
I'm creating a reusable framework for displaying notifications in an iOS application. I'd like the notification views to be added over the top of everything else in the application, sort of like a UIAlertView. When I init the manager that listens for NSNotification events and adds views in response, I need to get a reference to the top-most view in the application. This is what I have at the moment:
_topView = [[[[UIApplication sharedApplication] keyWindow] subviews] lastObject];
Would this work for any iOS application or is their a safer/better way to get the top view?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
每当我想在其他所有内容之上显示一些覆盖层时,我只需将其直接添加到应用程序窗口的顶部即可:
Whenever I want to display some overlay on top of everything else, I just add it on top of the Application Window directly:
问题有两个部分:顶部窗口,顶部窗口上的顶部视图。
所有现有的答案都错过了顶部窗口部分。但是
[[UIApplication sharedApplication] keyWindow]
不能保证是顶部窗口。顶部窗口。一个应用程序中不太可能同时存在两个具有相同
windowLevel
的窗口,因此我们可以按windowLevel
对所有窗口进行排序并获取最上面的窗口。顶部窗口的俯视图。只是为了完整。正如问题中已经指出的:
There are two parts of the problem: Top window, top view on top window.
All the existing answers missed the top window part. But
[[UIApplication sharedApplication] keyWindow]
is not guaranteed to be the top window.Top window. It is very unlikely that there will be two windows with the same
windowLevel
coexist for an app, so we can sort all the windows bywindowLevel
and get the topmost one.Top view on top window. Just to be complete. As already pointed out in the question:
通常,这将为您提供顶视图,但不能保证它对用户可见。例如,它可能位于屏幕之外,alpha 为 0.0,或者大小为 0x0。
也可能是 keyWindow 没有子视图,所以您应该首先测试它。这很不寻常,但也并非不可能。
UIWindow 是 UIView 的子类,因此如果您想确保您的通知对用户可见,您可以使用
addSubview:
将其直接添加到 keyWindow,它将立即成为最顶层的视图。我不确定这是否是您想要做的。 (根据你的问题,看来你已经知道这一点了。)Usually that will give you the top view, but there's no guarantee that it's visible to the user. It could be off the screen, have an alpha of 0.0, or could be have size of 0x0 for example.
It could also be that the keyWindow has no subviews, so you should probably test for that first. This would be unusual, but it's not impossible.
UIWindow is a subclass of UIView, so if you want to make sure your notification is visible to the user, you can add it directly to the keyWindow using
addSubview:
and it will instantly be the top most view. I'm not sure if this is what you're looking to do though. (Based on your question, it looks like you already know this.)实际上,您的应用程序中可能有多个 UIWindow。例如,如果屏幕上有键盘,则
[[UIApplication sharedApplication] windows]
将包含至少两个窗口(您的按键窗口和键盘窗口)。因此,如果您希望视图出现在它们两个之上,那么您必须执行以下操作:(
假设lastObject包含具有最高windowLevel优先级的窗口)。
Actually there could be more than one UIWindow in your application. For example, if a keyboard is on screen then
[[UIApplication sharedApplication] windows]
will contain at least two windows (your key-window and the keyboard window).So if you want your view to appear ontop of both of them then you gotta do something like:
(Assuming lastObject contains the window with the highest windowLevel priority).
我坚持标题所述的问题,而不是讨论。哪个视图在任何给定点上都是可见的?
可以直接与任何 UIWindow 作为接收器或任何 UIView 作为接收器一起使用。
I'm sticking to the question as the title states and not the discussion. Which view is top visible on any given point?
Can be used directly with any UIWindow as receiver or any UIView as receiver.
如果您要添加加载视图(例如活动指示器视图),请确保您有 UIWindow 类的对象。如果您在显示加载视图之前显示操作表,则
keyWindow
将是UIActionSheet
而不是UIWindow
。由于操作表将消失,加载视图也将随之消失。或者这就是给我带来问题的原因。If you are adding a loading view (an activity indicator view for instance), make sure you have an object of UIWindow class. If you show an action sheet just before you show your loading view, the
keyWindow
will be theUIActionSheet
and notUIWindow
. And since the action sheet will go away, the loading view will go away with it. Or that's what was causing me problems.如果您的应用程序仅在纵向方向上工作,这就足够了:
并且您的视图将不会显示在键盘和状态栏上。
如果您想获得键盘或状态栏上的最顶层视图,或者您希望最顶层视图可以随设备正确旋转,请尝试此框架:
https://github.com/HarrisonXi/TopmostView
支持iOS7/8/9。
If your application only works in portrait orientation, this is enough:
And your view will not be shown over keyboard and status bar.
If you want to get a topmost view that over keyboard or status bar, or you want the topmost view can rotate correctly with devices, please try this framework:
https://github.com/HarrisonXi/TopmostView
It supports iOS7/8/9.
如果您想在屏幕上的所有内容上方添加视图,只需使用此代码即可。
Just use this code if you want to add a view above of everything in the screen.
试试这个
try this