获取对 iOS 应用程序中最顶层视图/窗口的引用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3843411/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Getting reference to the top-most view/window in iOS application
提问by typeoneerror
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:
我正在创建一个可重用的框架,用于在 iOS 应用程序中显示通知。我希望将通知视图添加到应用程序中其他所有内容的顶部,有点像 UIAlertView。当我初始化监听 NSNotification 事件并添加视图作为响应的管理器时,我需要获取对应用程序中最顶层视图的引用。这就是我目前所拥有的:
_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?
这是否适用于任何 iOS 应用程序,或者它们是获得顶视图的更安全/更好的方式吗?
采纳答案by Kris Markel
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.
通常这会给你顶视图,但不能保证它对用户可见。例如,它可能不在屏幕上,alpha 为 0.0,或者大小可能为 0x0。
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.
也可能是 keyWindow 没有子视图,所以你应该先测试一下。这将是不寻常的,但这并非不可能。
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 是 UIView 的子类,所以如果你想确保你的通知对用户可见,你可以直接将它添加到 keyWindow 使用addSubview:
,它会立即成为最顶层的视图。我不确定这是否是你想要做的。(根据您的问题,您似乎已经知道这一点。)
回答by samvermette
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] addSubview:someView]
回答by an0
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.
所有现有答案都错过了顶部窗口部分。但[[UIApplication sharedApplication] keyWindow]
不能保证是顶部窗口。
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.UIWindow *topWindow = [[[UIApplication sharedApplication].windows sortedArrayUsingComparator:^NSComparisonResult(UIWindow *win1, UIWindow *win2) { return win1.windowLevel - win2.windowLevel; }] lastObject];
Top view on top window. Just to be complete. As already pointed out in the question:
UIView *topView = [[topWindow subviews] lastObject];
顶部窗户。
windowLevel
一个应用程序不太可能有两个相同的窗口共存,因此我们可以对所有窗口进行排序windowLevel
并获得最上面的一个。UIWindow *topWindow = [[[UIApplication sharedApplication].windows sortedArrayUsingComparator:^NSComparisonResult(UIWindow *win1, UIWindow *win2) { return win1.windowLevel - win2.windowLevel; }] lastObject];
顶部窗口的顶部视图。只是为了完整。正如问题中已经指出的那样:
UIView *topView = [[topWindow subviews] lastObject];
回答by lorean
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).
实际上,您的应用程序中可能有多个 UIWindow。例如,如果屏幕上有一个键盘,那么[[UIApplication sharedApplication] windows]
它将包含至少两个窗口(您的键窗口和键盘窗口)。
So if you want your view to appear ontop of both of them then you gotta do something like:
因此,如果您希望您的视图出现在它们两者之上,那么您必须执行以下操作:
[[[[UIApplication sharedApplication] windows] lastObject] addSubview:view];
(Assuming lastObject contains the window with the highest windowLevel priority).
(假设 lastObject 包含具有最高 windowLevel 优先级的窗口)。
回答by hfossli
I'm sticking to the question as the title states and not the discussion. Which view is top visible on any given point?
我坚持标题所说的问题,而不是讨论。在任何给定点上哪个视图是顶部可见的?
@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
Can be used directly with any UIWindow as receiver or any UIView as receiver.
可以直接使用任何 UIWindow 作为接收器或任何 UIView 作为接收器。
回答by Miha Hribar
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 the UIActionSheet
and not UIWindow
. And since the action sheet will go away, the loading view will go away with it. Or that's what was causing me problems.
如果您要添加加载视图(例如活动指示器视图),请确保您拥有 UIWindow 类的对象。如果您在显示加载视图之前显示操作表,keyWindow
则将是UIActionSheet
而不是UIWindow
。并且由于操作表将消失,加载视图将随之消失。或者这就是给我带来问题的原因。
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;
}
}
}
回答by Harrison Xi
If your application only works in portrait orientation, this is enough:
如果您的应用程序只能在纵向模式下工作,那么这就足够了:
[[[UIApplication sharedApplication] keyWindow] addSubview:yourView]
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
https://github.com/HarrisonXi/TopmostView
It supports iOS7/8/9.
它支持iOS7/8/9。
回答by Chandramani
try this
尝试这个
UIWindow *window = [[[UIApplication sharedApplication] windows] lastObject];
回答by handiansom
Just use this code if you want to add a view above of everything in the screen.
如果您想在屏幕上的所有内容上方添加一个视图,只需使用此代码。
[[UIApplication sharedApplication].keyWindow addSubView: yourView];
回答by user12775146
UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
if (![NSStringFromClass([keyWindow class]) isEqualToString:@"UIWindow"]) {
NSArray *windows = [UIApplication sharedApplication].windows;
for (UIWindow *window in windows) {
if ([NSStringFromClass([window class]) isEqualToString:@"UIWindow"]) {
keyWindow = window;
break;
}
}
}