UIApplication.sharedApplication.delegate.window 和 UIApplication.sharedApplication.keyWindow 有啥区别?

Posted

技术标签:

【中文标题】UIApplication.sharedApplication.delegate.window 和 UIApplication.sharedApplication.keyWindow 有啥区别?【英文标题】:What is the difference between UIApplication.sharedApplication.delegate.window and UIApplication.sharedApplication.keyWindow?UIApplication.sharedApplication.delegate.window 和 UIApplication.sharedApplication.keyWindow 有什么区别? 【发布时间】:2014-02-11 09:56:47 【问题描述】:

谁能帮我理解以下两行之间的区别:

[UIApplication.sharedApplication.delegate.window addSubview:myView];
[UIApplication.sharedApplication.keyWindow addSubview:myView];

【问题讨论】:

【参考方案1】:

对于大多数用途,它们将是相同的……但并非总是如此。

[UIApplication sharedApplication].keyWindow 是当前在设备上显示的窗口。这通常是您应用程序的窗口,但也可以是系统窗口。

[UIApplication sharedApplication].delegate.window 是您的应用程序预期使用的窗口。

应该使用哪一个?好吧,这一切都取决于上下文。

如果您要更新应用程序的一部分,那么您应该将视图添加到应用程序的窗口中。这几乎总是您想要做的。

就个人而言,当我需要直接向窗口添加视图时,我总是使用[[UIApplication sharedApplication].delegate.window addSubview:view][self.view.window addSubView:view](在UIViewController 内)。

有时您可能希望向当前正在显示的窗口呈现视图,无论该窗口属于您的应用程序还是某个系统窗口。我没有遇到过这种情况。

【讨论】:

由于您不知道最后出现的是哪个屏幕...当您收到远程通知时使用keyWindow 显示警报是否会更好?我说的是早于 ios10 的 iOS 版本,你没有 willPresent?【参考方案2】:

它们在 iOS 上可能是相同的。当它们不同时,通常您会呈现除应用程序委托的主窗口之外的另一个窗口。您的应用可以有多个窗口,但只有 keyWindow 是在屏幕上可见并接收事件的窗口(示例可能是 UIAlert 可见并接收事件时它是键窗口)参考:https://developer.apple.com/library/content/documentation/WindowsViews/Conceptual/WindowAndScreenGuide/WindowScreenRolesinApp/WindowScreenRolesinApp.html

来自文档:

对于UIApplication.sharedApplication.delegate.window

呈现故事板时使用的窗口。该属性包含 用于在设备上显示应用程序视觉内容的窗口 主屏幕。

即这是您在AppDelegate.h 文件中拥有的属性window

对于UIApplication.sharedApplication.keyWindow

此属性在 windows 数组中保存 UIWindow 对象,即 最近发送了 makeKeyAndVisible 消息。

在 iOS 上,您在 AppDelegate.m 内部调用 makeKeyAndVisible

application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

您将创建的 appDelegate 窗口设为 keyWindow。通常,银行应用在后台切换按键窗口,以保护用户在双击主页按钮时的敏感信息,并在应用处于前台时切换回主代理窗口。

此答案与@SipkeSchoorstra、@D-Mx 和@andyDarwin 合作

【讨论】:

投反对票,因为这不正确,请参阅 Jeffrey Thomas 和 Andy Darwin 的回答。 @SipkeSchoorstra 感谢您的反馈,答案已更新。 这是错误的。不仅 keyWindow 是可见的,例如警报使用单独的窗口来显示。当一个窗口当前正在接收键盘和非触摸相关事件时,它被认为是关键窗口。见developer.apple.com/library/content/documentation/WindowsViews/… 嘿@D-Mx,是的,看起来我忘了提到关键窗口是可见的并且正在接收事件,刚刚更新以包含它。我想说答案没有错,但不完整,感谢您帮助使 *** 变得友好和协作:)【参考方案3】:

Basheer_CAD 的回答不对。它们在 iOS 中并不总是相同的。

Jeffery Thomas 的回答是正确的,让我提供一个具体的例子。

- (void)viewDidLoad 
    [super viewDidLoad];
    NSLog(@"keyWindow --------> %@",[UIApplication sharedApplication].keyWindow.rootViewController);
    NSLog(@"delegate.window --> %@",[UIApplication sharedApplication].delegate.window.rootViewController);
    NSLog(@"self.view.window -> %@",self.view.window.rootViewController);


- (void)viewDidAppear:(BOOL)animated 
    [super viewDidAppear:animated];
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"title" message:@"message" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:nil];
    [alert show];
    NSLog(@"keyWindow --------> %@",[UIApplication sharedApplication].keyWindow.rootViewController);
    NSLog(@"delegate.window --> %@",[UIApplication sharedApplication].delegate.window.rootViewController);
    NSLog(@"self.view.window -> %@",self.view.window.rootViewController);

输出是:

keyWindow --------> (null)
delegate.window --> <ViewController: 0x10030c0e0>
self.view.window -> (null)
keyWindow --------> <UIApplicationRotationFollowingController: 0x100204510>
delegate.window --> <ViewController: 0x10030c0e0>
self.view.window -> <ViewController: 0x10030c0e0>

viewDidLoad时,实际上窗口还没有准备好,所以系统窗口什么都没有。 UIAlertView 可能主宰了窗口,所以你无法得到你想要的窗口。

【讨论】:

感谢您的反馈,请查看我的更新答案。因此,您的答案被赞成:)【参考方案4】:

最简单的设置是只有一个UIWindow。通常,该窗口作为您的应用程序委托的属性保留。 keyWindow 是指定接收键盘和其他与触摸无关的事件。一次只能有一个窗口是关键窗口。因此,如果您添加第二个窗口并将其设为keyWindow(通过[window makeKeyAndVisible]),您的行将返回不同的窗口!

【讨论】:

以上是关于UIApplication.sharedApplication.delegate.window 和 UIApplication.sharedApplication.keyWindow 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章