由于iOS13及以后引入了SceneDelegate,导致不能通过原来的[UIApplication sharedApplication].keyWindow直接获取到正确的keyWindow。需要区分系统来获取。具体的实现如下:
/** 获取 keyWindow */ static inline UIWindow *BRGetKeyWindow(void) { UIWindow *keyWindow = nil; #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 // 编译时检查SDK版本:Xcode11+编译会调用(iOS SDK 13.0 以后版本的处理) if (@available(iOS 13.0, *)) { NSSet<UIScene *> *connectedScenes = [UIApplication sharedApplication].connectedScenes; for (UIScene *scene in connectedScenes) { if (scene.activationState == UISceneActivationStateForegroundActive && [scene isKindOfClass:[UIWindowScene class]]) { UIWindowScene *windowScene = (UIWindowScene *)scene; for (UIWindow *window in windowScene.windows) { if (window.isKeyWindow) { keyWindow = window; break; } } } } } else #endif { #if __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 return [UIApplication sharedApplication].keyWindow; #endif } return keyWindow; }
内联函数的使用和宏类似,它主要为了代替无检查机制的宏,具体使用如下:
#define Base_BottomHeight ([FMConfig config].safeBottomHeight) // 底部安全区域高度 #define BR_BOTTOM_MARGIN \ ({CGFloat safeBottomHeight = 0;\ if (@available(iOS 11.0, *)) {\ safeBottomHeight = BRGetKeyWindow().safeAreaInsets.bottom;\ }\ (safeBottomHeight);})