有谁能帮我理解以下两行代码的区别:
[UIApplication.sharedApplication.delegate.window addSubview:myView];
[UIApplication.sharedApplication.keyWindow addSubview:myView];
有谁能帮我理解以下两行代码的区别:
[UIApplication.sharedApplication.delegate.window addSubview:myView];
[UIApplication.sharedApplication.keyWindow addSubview:myView];
对于大多数用途,它们将是相同的...但并非总是如此。
[UIApplication sharedApplication].keyWindow
是当前在设备上显示的窗口。这通常是您的应用程序窗口,但也可能是系统窗口。
[UIApplication sharedApplication].delegate.window
是您的应用程序预期使用的窗口。
那么应该使用哪个呢?这完全取决于上下文。
如果您正在更新应用程序的某个部分,则应将视图添加到应用程序的窗口。这几乎总是您想要做的事情。
就我个人而言,当我需要直接将视图添加到窗口时,我总是使用 [[UIApplication sharedApplication].delegate.window addSubview:view]
或 [self.view.window addSubView:view]
(在UIViewController
中)。
有时,您可能希望将视图呈现到当前显示的窗口,而不管该窗口是否属于您的应用程序或是某个系统窗口。我还没有遇到过这种情况。
keyWindow
是可见于屏幕并接收事件的窗口(例如,当UIAlert可见并接收事件时,它是keywindow)。参考:https://developer.apple.com/library/content/documentation/WindowsViews/Conceptual/WindowAndScreenGuide/WindowScreenRolesinApp/WindowScreenRolesinApp.htmlUIApplication.sharedApplication.delegate.window
:AppDelegate.h
文件中拥有的window
属性。UIApplication.sharedApplication.keyWindow
:AppDelegate.m
内调用makeKeyAndVisible
,如下所示:
application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
你使创建的应用委托窗口成为keyWindow。通常,银行应用程序在将应用程序放在后台以保护用户敏感信息时切换关键窗口,并在应用程序处于前台时切换回主委托窗口。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
可能会占用窗口,所以你无法获取想要的窗口。
最简单的设置就是只有一个UIWindow
。通常这个窗口被保存为您的应用程序委托的属性。 keyWindow
是指定接收键盘和其他非触摸相关事件的窗口。一次只能有一个窗口成为关键窗口。因此,如果您添加第二个窗口并将其设置为keyWindow
(通过[window makeKeyAndVisible]
),则会返回不同的窗口!
keyWindow
显示警报是否是个好主意?我指的是iOS10之前的iOS版本,在那里您没有willPresent
。 - mfaani