From 0de42863214dfc0c9dd63ae3ba2bd323006d0b97 Mon Sep 17 00:00:00 2001 From: wsr1949 <921903719@qq.com> Date: Tue, 11 Nov 2025 18:31:40 +0800 Subject: [PATCH 1/3] Implement qmui_contentView method for UINavigationBar Add method to retrieve contentView for UINavigationBar in iOS 26 and later. --- .../UIKitExtensions/UINavigationBar+QMUI.m | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/QMUIKit/UIKitExtensions/UINavigationBar+QMUI.m b/QMUIKit/UIKitExtensions/UINavigationBar+QMUI.m index 8d82a777..cb596c4f 100644 --- a/QMUIKit/UIKitExtensions/UINavigationBar+QMUI.m +++ b/QMUIKit/UIKitExtensions/UINavigationBar+QMUI.m @@ -359,6 +359,25 @@ + (void)load { } - (UIView *)qmui_contentView { + if (@available(iOS 26.0, *)) { + // 如果 contentView 已经被构造出来,则通过遍历 view 层级树的方式获取 + UIView *contentView = [self.subviews qmui_firstMatchWithBlock:^BOOL(__kindof UIView * _Nonnull item) { + return [NSStringFromClass(item.class) containsString:@"ContentView"]; + }]; + if (contentView) return contentView; + + // Xcode 26 编译在 iOS 26 上时,无法用以前的 KVC 方式获取 contentView,所以改为通过 Ivar 获取 + NSObject *provider = [self valueForKey:@"visualProvider"]; + __block UIView *result = nil; + [provider qmui_enumrateIvarsUsingBlock:^(Ivar _Nonnull ivar, NSString * _Nonnull ivarDescription) { + if (!result && [ivarDescription containsString:@"contentView"]) { + result = getObjectIvarValue(provider, ivar); + } + }]; + return result; + } + + // 在 bar init 完即可获取到 contentView,虽然此时尚未被添加到 view 上 return [self valueForKeyPath:@"visualProvider.contentView"]; } From 65b494f346f39541001509b480d3b4c2f9202c0a Mon Sep 17 00:00:00 2001 From: "921903719@qq.com" <921903719@qq.com> Date: Thu, 12 Mar 2026 17:47:10 +0800 Subject: [PATCH 2/3] Update NSObject+QMUI.m --- QMUIKit/UIKitExtensions/NSObject+QMUI.m | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/QMUIKit/UIKitExtensions/NSObject+QMUI.m b/QMUIKit/UIKitExtensions/NSObject+QMUI.m index 9fd21b90..2346bb32 100644 --- a/QMUIKit/UIKitExtensions/NSObject+QMUI.m +++ b/QMUIKit/UIKitExtensions/NSObject+QMUI.m @@ -262,7 +262,25 @@ @implementation NSObject (QMUI_KeyValueCoding) - (id)qmui_valueForKey:(NSString *)key { if ([self isKindOfClass:[UIView class]] && QMUICMIActivated && !IgnoreKVCAccessProhibited) { BeginIgnoreUIKVCAccessProhibited - id value = [self valueForKey:key]; + + id value = nil; + // 修复:增加 KVC 键合法性校验,避免访问未定义的 key 导致崩溃 + if ([self respondsToSelector:NSSelectorFromString(key)] || + [self.class instancesRespondToSelector:NSSelectorFromString(key)] || + [self.class accessInstanceVariablesDirectly]) { + // 方式1:优先通过 selector 访问(方法/属性) + SEL getterSel = NSSelectorFromString(key); + if ([self respondsToSelector:getterSel]) { + value = ((id (*)(id, SEL))objc_msgSend)(self, getterSel); + } else { + // 方式2:校验实例变量存在性后再通过 KVC 访问 + Ivar ivar = class_getInstanceVariable([self class], [key UTF8String]); + if (ivar) { + value = [self valueForKey:key]; + } + } + } + EndIgnoreUIKVCAccessProhibited return value; } From 56d209e3b2c2829f7caa5e1a683e0dfee272036f Mon Sep 17 00:00:00 2001 From: "921903719@qq.com" <921903719@qq.com> Date: Wed, 14 Oct 2026 15:32:49 +0800 Subject: [PATCH 3/3] =?UTF-8?q?window=E4=BD=BF=E7=94=A8Scene=E7=AA=97?= =?UTF-8?q?=E5=8F=A3=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 +- QMUIKit/QMUIComponents/QMUIKeyboardManager.m | 19 +++--- .../QMUIModalPresentationViewController.h | 2 +- .../QMUIModalPresentationViewController.m | 9 +-- .../QMUIComponents/QMUIPopupContainerView.m | 5 +- .../QMUITheme/QMUIThemeManager.m | 3 +- QMUIKit/QMUICore/QMUICommonDefines.h | 5 ++ QMUIKit/QMUICore/QMUIConfiguration.m | 2 +- QMUIKit/UIKitExtensions/UIApplication+QMUI.h | 7 ++ QMUIKit/UIKitExtensions/UIApplication+QMUI.m | 67 +++++++++++++++++++ .../UIKitExtensions/UIMenuController+QMUI.m | 5 +- QMUIKit/UIKitExtensions/UIView+QMUI.m | 2 +- QMUIKit/UIKitExtensions/UIWindow+QMUI.m | 5 +- 13 files changed, 108 insertions(+), 25 deletions(-) diff --git a/.gitignore b/.gitignore index 82ed296f..9ea2e532 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ .DS_Store xcuserdata/ - +.derivedData/ diff --git a/QMUIKit/QMUIComponents/QMUIKeyboardManager.m b/QMUIKit/QMUIComponents/QMUIKeyboardManager.m index 178df3ec..3a98b974 100644 --- a/QMUIKit/QMUIComponents/QMUIKeyboardManager.m +++ b/QMUIKit/QMUIComponents/QMUIKeyboardManager.m @@ -15,6 +15,7 @@ #import "QMUIKeyboardManager.h" #import "QMUICore.h" +#import "UIApplication+QMUI.h" #import "QMUILog.h" #import "QMUIAppearance.h" #import "QMUIMultipleDelegates.h" @@ -396,10 +397,10 @@ - (UIResponder *)unPackageTargetResponder:(NSValue *)value { } - (UIResponder *)firstResponderInWindows { - UIResponder *responder = [UIApplication.sharedApplication.keyWindow qmui_findFirstResponder]; + UIResponder *responder = [UIApplication.sharedApplication.qmui_keyWindow qmui_findFirstResponder]; if (!responder) { - for (UIWindow *window in UIApplication.sharedApplication.windows) { - if (window != UIApplication.sharedApplication.keyWindow) { + for (UIWindow *window in UIApplication.sharedApplication.qmui_windows) { + if (window != UIApplication.sharedApplication.qmui_keyWindow) { responder = [window qmui_findFirstResponder]; if (responder) { return responder; @@ -720,7 +721,7 @@ - (void)keyboardDidChangedFrame:(UIView *)keyboardView { self.keyboardMoveBeginRect = endFrame; if (self.currentResponder) { - UIWindow *mainWindow = UIApplication.sharedApplication.keyWindow ?: UIApplication.sharedApplication.delegate.window; + UIWindow *mainWindow = UIApplication.sharedApplication.qmui_keyWindow ?: UIApplication.sharedApplication.delegate.window; if (mainWindow) { CGRect keyboardRect = keyboardMoveUserInfo.endFrame; CGFloat distanceFromBottom = [QMUIKeyboardManager distanceFromMinYToBottomInView:mainWindow keyboardRect:keyboardRect]; @@ -793,7 +794,7 @@ + (CGRect)convertKeyboardRect:(CGRect)rect toView:(UIView *)view { return rect; } - UIWindow *mainWindow = UIApplication.sharedApplication.keyWindow ?: UIApplication.sharedApplication.delegate.window; + UIWindow *mainWindow = UIApplication.sharedApplication.qmui_keyWindow ?: UIApplication.sharedApplication.delegate.window; if (!mainWindow) { if (view) { [view convertRect:rect fromView:nil]; @@ -855,7 +856,7 @@ + (CGFloat)distanceFromMinYToBottomInView:(UIView *)view keyboardRect:(CGRect)re 所以只要找到 UIInputSetHostView 即可,优先从 UIRemoteKeyboardWindow 找,不存在的话则从 UITextEffectsWindow 找。 */ + (UIView *)keyboardView { - UIView *inputSetHostView = [[UIApplication.sharedApplication.windows qmui_filterWithBlock:^BOOL(__kindof UIWindow * _Nonnull window) { + UIView *inputSetHostView = [[UIApplication.sharedApplication.qmui_windows qmui_filterWithBlock:^BOOL(__kindof UIWindow * _Nonnull window) { return [NSStringFromClass(window.class) isEqualToString:@"UIRemoteKeyboardWindow"]; }] qmui_compactMapWithBlock:^id _Nullable(__kindof UIWindow * _Nonnull window) { return [self inputSetHostViewInWindow:window]; @@ -863,7 +864,7 @@ + (UIView *)keyboardView { if (inputSetHostView) return inputSetHostView; - inputSetHostView = [[UIApplication.sharedApplication.windows qmui_filterWithBlock:^BOOL(__kindof UIWindow * _Nonnull window) { + inputSetHostView = [[UIApplication.sharedApplication.qmui_windows qmui_filterWithBlock:^BOOL(__kindof UIWindow * _Nonnull window) { return [NSStringFromClass(window.class) isEqualToString:@"UITextEffectsWindow"]; }] qmui_compactMapWithBlock:^id _Nullable(__kindof UIWindow * _Nonnull window) { return [self inputSetHostViewInWindow:window]; @@ -885,14 +886,14 @@ + (UIWindow *)keyboardWindow { UIView *inputSetHostView = [self keyboardView]; if (inputSetHostView) return inputSetHostView.window; - UIWindow *window = [UIApplication.sharedApplication.windows qmui_firstMatchWithBlock:^BOOL(__kindof UIWindow * _Nonnull item) { + UIWindow *window = [UIApplication.sharedApplication.qmui_windows qmui_firstMatchWithBlock:^BOOL(__kindof UIWindow * _Nonnull item) { return [NSStringFromClass(item.class) isEqualToString:@"UIRemoteKeyboardWindow"]; }]; if (window) { return window; } - window = [UIApplication.sharedApplication.windows qmui_firstMatchWithBlock:^BOOL(__kindof UIWindow * _Nonnull item) { + window = [UIApplication.sharedApplication.qmui_windows qmui_firstMatchWithBlock:^BOOL(__kindof UIWindow * _Nonnull item) { return [NSStringFromClass(item.class) isEqualToString:@"UITextEffectsWindow"]; }]; return window; diff --git a/QMUIKit/QMUIComponents/QMUIModalPresentationViewController.h b/QMUIKit/QMUIComponents/QMUIModalPresentationViewController.h index b44011fa..7294f359 100644 --- a/QMUIKit/QMUIComponents/QMUIModalPresentationViewController.h +++ b/QMUIKit/QMUIComponents/QMUIModalPresentationViewController.h @@ -314,7 +314,7 @@ typedef NS_ENUM(NSUInteger, QMUIModalPresentationAnimationStyle) { @end -/// 专用于QMUIModalPresentationViewController的UIWindow,这样才能在`UIApplication.sharedApplication.windows`里方便地区分出来 +/// 专用于QMUIModalPresentationViewController的UIWindow,这样才能在`UIApplication.sharedApplication.qmui_windows`里方便地区分出来 @interface QMUIModalPresentationWindow : UIWindow @end diff --git a/QMUIKit/QMUIComponents/QMUIModalPresentationViewController.m b/QMUIKit/QMUIComponents/QMUIModalPresentationViewController.m index 5355412f..bc74838f 100644 --- a/QMUIKit/QMUIComponents/QMUIModalPresentationViewController.m +++ b/QMUIKit/QMUIComponents/QMUIModalPresentationViewController.m @@ -15,6 +15,7 @@ #import "QMUIModalPresentationViewController.h" #import "QMUICore.h" +#import "UIApplication+QMUI.h" #import "UIViewController+QMUI.h" #import "UIView+QMUI.h" #import "QMUIKeyboardManager.h" @@ -271,7 +272,7 @@ - (void)viewWillDisappear:(BOOL)animated { if (self.shownInWindowMode) { // 恢复 keyWindow 之前做一下检查,避免这个问题 https://github.com/Tencent/QMUI_iOS/issues/90 - if (UIApplication.sharedApplication.keyWindow == self.window) { + if (UIApplication.sharedApplication.qmui_keyWindow == self.window) { if (self.previousKeyWindow.hidden) { // 保护了这个 issue 记录的情况,避免主 window 丢失 keyWindow https://github.com/Tencent/QMUI_iOS/issues/315 [UIApplication.sharedApplication.delegate.window makeKeyWindow]; @@ -505,7 +506,7 @@ - (void)showWithAnimated:(BOOL)animated completion:(void (^)(BOOL))completion { // makeKeyAndVisible 导致的 viewWillAppear: 必定 animated 是 NO 的,所以这里用额外的变量保存这个 animated 的值 self.appearAnimated = animated; self.appearCompletionBlock = completion; - self.previousKeyWindow = UIApplication.sharedApplication.keyWindow; + self.previousKeyWindow = UIApplication.sharedApplication.qmui_keyWindow; if (!self.window) { self.window = [[QMUIModalPresentationWindow alloc] init]; self.window.windowLevel = UIWindowLevelQMUIAlertView; @@ -751,7 +752,7 @@ - (UIViewController *)childViewControllerForHomeIndicatorAutoHidden { @implementation QMUIModalPresentationViewController (Manager) + (BOOL)isAnyModalPresentationViewControllerVisible { - for (UIWindow *window in UIApplication.sharedApplication.windows) { + for (UIWindow *window in UIApplication.sharedApplication.qmui_windows) { if ([window isKindOfClass:[QMUIModalPresentationWindow class]] && !window.hidden) { return YES; } @@ -763,7 +764,7 @@ + (BOOL)hideAllVisibleModalPresentationViewControllerIfCan { BOOL hideAllFinally = YES; - for (UIWindow *window in UIApplication.sharedApplication.windows) { + for (UIWindow *window in UIApplication.sharedApplication.qmui_windows) { if (![window isKindOfClass:[QMUIModalPresentationWindow class]]) { continue; } diff --git a/QMUIKit/QMUIComponents/QMUIPopupContainerView.m b/QMUIKit/QMUIComponents/QMUIPopupContainerView.m index dd76738c..9312f09f 100644 --- a/QMUIKit/QMUIComponents/QMUIPopupContainerView.m +++ b/QMUIKit/QMUIComponents/QMUIPopupContainerView.m @@ -15,6 +15,7 @@ #import "QMUIPopupContainerView.h" #import "QMUICore.h" +#import "UIApplication+QMUI.h" #import "QMUICommonViewController.h" #import "UIViewController+QMUI.h" #import "QMUILog.h" @@ -697,7 +698,7 @@ - (void)showWithAnimated:(BOOL)animated completion:(void (^)(BOOL))completion { QMUICommonViewController *viewController = (QMUICommonViewController *)self.popupWindow.rootViewController; viewController.supportedOrientationMask = [QMUIHelper visibleViewController].supportedInterfaceOrientations; - self.previousKeyWindow = UIApplication.sharedApplication.keyWindow; + self.previousKeyWindow = UIApplication.sharedApplication.qmui_keyWindow; [self.popupWindow makeKeyAndVisible]; isShowingByWindowMode = YES; @@ -798,7 +799,7 @@ - (void)hideWithAnimated:(BOOL)animated completion:(void (^)(BOOL))completion { - (void)hideCompletionWithWindowMode:(BOOL)windowMode completion:(void (^)(BOOL))completion { if (windowMode) { // 恢复 keyWindow 之前做一下检查,避免类似问题 https://github.com/Tencent/QMUI_iOS/issues/90 - if (UIApplication.sharedApplication.keyWindow == self.popupWindow) { + if (UIApplication.sharedApplication.qmui_keyWindow == self.popupWindow) { [self.previousKeyWindow makeKeyWindow]; } diff --git a/QMUIKit/QMUIComponents/QMUITheme/QMUIThemeManager.m b/QMUIKit/QMUIComponents/QMUITheme/QMUIThemeManager.m index d73a5326..1a5efa60 100644 --- a/QMUIKit/QMUIComponents/QMUITheme/QMUIThemeManager.m +++ b/QMUIKit/QMUIComponents/QMUITheme/QMUIThemeManager.m @@ -14,6 +14,7 @@ #import "QMUIThemeManager.h" #import "QMUICore.h" +#import "UIApplication+QMUI.h" #import "UIView+QMUITheme.h" #import "UIViewController+QMUITheme.h" #import "QMUIThemePrivate.h" @@ -137,7 +138,7 @@ - (void)removeTheme:(NSObject *)theme { - (void)notifyThemeChanged { [[NSNotificationCenter defaultCenter] postNotificationName:QMUIThemeDidChangeNotification object:self]; - [UIApplication.sharedApplication.windows enumerateObjectsUsingBlock:^(__kindof UIWindow * _Nonnull window, NSUInteger idx, BOOL * _Nonnull stop) { + [UIApplication.sharedApplication.qmui_windows enumerateObjectsUsingBlock:^(__kindof UIWindow * _Nonnull window, NSUInteger idx, BOOL * _Nonnull stop) { if (!window.hidden && window.alpha > 0.01 && window.rootViewController) { [window.rootViewController qmui_themeDidChangeByManager:self identifier:self.currentThemeIdentifier theme:self.currentTheme]; diff --git a/QMUIKit/QMUICore/QMUICommonDefines.h b/QMUIKit/QMUICore/QMUICommonDefines.h index 8f77b6d4..0624462c 100644 --- a/QMUIKit/QMUICore/QMUICommonDefines.h +++ b/QMUIKit/QMUICore/QMUICommonDefines.h @@ -81,6 +81,11 @@ #define IOS18_SDK_ALLOWED YES #endif +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 270000 +/// 当前编译使用的 Base SDK 版本为 iOS 27.0 及以上 +#define IOS27_SDK_ALLOWED YES +#endif + #pragma mark - Clang #define ArgumentToString(macro) #macro diff --git a/QMUIKit/QMUICore/QMUIConfiguration.m b/QMUIKit/QMUICore/QMUIConfiguration.m index ef74deb8..701ba05c 100644 --- a/QMUIKit/QMUICore/QMUIConfiguration.m +++ b/QMUIKit/QMUICore/QMUIConfiguration.m @@ -1029,7 +1029,7 @@ - (void)setDefaultStatusBarStyle:(UIStatusBarStyle)defaultStatusBarStyle { - (NSArray *)appearanceUpdatingViewControllersOfClasses:(NSArray> *)classes { if (!classes.count) return nil; NSMutableArray *viewControllers = [NSMutableArray array]; - [UIApplication.sharedApplication.windows enumerateObjectsUsingBlock:^(__kindof UIWindow * _Nonnull window, NSUInteger idx, BOOL * _Nonnull stop) { + [UIApplication.sharedApplication.qmui_windows enumerateObjectsUsingBlock:^(__kindof UIWindow * _Nonnull window, NSUInteger idx, BOOL * _Nonnull stop) { if (window.rootViewController) { [viewControllers addObjectsFromArray:[window.rootViewController qmui_existingViewControllersOfClasses:classes]]; } diff --git a/QMUIKit/UIKitExtensions/UIApplication+QMUI.h b/QMUIKit/UIKitExtensions/UIApplication+QMUI.h index 94250659..af6b7085 100644 --- a/QMUIKit/UIKitExtensions/UIApplication+QMUI.h +++ b/QMUIKit/UIKitExtensions/UIApplication+QMUI.h @@ -20,6 +20,13 @@ NS_ASSUME_NONNULL_BEGIN /// 判断当前的 App 是否已经完全启动 @property(nonatomic, assign, readonly) BOOL qmui_didFinishLaunching; + +/// 通过 Scene 获取当前 keyWindow,等价于 iOS 27 之前 `UIApplication.keyWindow` 的语义。若找不到则返回 nil。 +@property(nullable, nonatomic, readonly) UIWindow *qmui_keyWindow; + +/// 通过 Scene 聚合当前 App 的所有 window,等价于 iOS 27 之前 `UIApplication.windows` 的语义。 +@property(nonatomic, copy, readonly) NSArray *qmui_windows; + @end NS_ASSUME_NONNULL_END diff --git a/QMUIKit/UIKitExtensions/UIApplication+QMUI.m b/QMUIKit/UIKitExtensions/UIApplication+QMUI.m index 36129ad3..db253fb4 100644 --- a/QMUIKit/UIKitExtensions/UIApplication+QMUI.m +++ b/QMUIKit/UIKitExtensions/UIApplication+QMUI.m @@ -15,6 +15,23 @@ #import "UIApplication+QMUI.h" #import "QMUICore.h" +static UIWindow *QMUIKeyWindowInWindowScenes(NSSet *connectedScenes, NSIndexSet *allowedActivationStates) { + for (UIScene *scene in connectedScenes) { + if (![scene isKindOfClass:[UIWindowScene class]]) { + continue; + } + if (allowedActivationStates && ![allowedActivationStates containsIndex:scene.activationState]) { + continue; + } + for (UIWindow *window in ((UIWindowScene *)scene).windows) { + if (window.isKeyWindow) { + return window; + } + } + } + return nil; +} + @implementation UIApplication (QMUI) QMUISynthesizeBOOLProperty(qmui_didFinishLaunching, setQmui_didFinishLaunching) @@ -45,4 +62,54 @@ - (void)qmui_handleDidFinishLaunchingNotification:(NSNotification *)notification [NSNotificationCenter.defaultCenter removeObserver:self name:UIApplicationDidFinishLaunchingNotification object:nil]; } +- (UIWindow *)qmui_keyWindow { + static NSIndexSet *foregroundActiveStates; + static NSIndexSet *foregroundStates; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + foregroundActiveStates = [NSIndexSet indexSetWithIndex:UISceneActivationStateForegroundActive]; + NSMutableIndexSet *states = [NSMutableIndexSet indexSet]; + [states addIndex:UISceneActivationStateForegroundInactive]; + [states addIndex:UISceneActivationStateForegroundActive]; + foregroundStates = states; + }); + + UIWindow *keyWindow = QMUIKeyWindowInWindowScenes(self.connectedScenes, foregroundActiveStates); + if (!keyWindow) { + keyWindow = QMUIKeyWindowInWindowScenes(self.connectedScenes, foregroundStates); + } + if (!keyWindow) { + keyWindow = QMUIKeyWindowInWindowScenes(self.connectedScenes, nil); + } +#ifndef IOS27_SDK_ALLOWED + if (!keyWindow) { + BeginIgnoreDeprecatedWarning + keyWindow = self.keyWindow; + EndIgnoreDeprecatedWarning + } +#endif + return keyWindow; +} + +- (NSArray *)qmui_windows { + NSMutableArray *windows = [NSMutableArray array]; + for (UIScene *scene in self.connectedScenes) { + if (![scene isKindOfClass:[UIWindowScene class]]) { + continue; + } + [windows addObjectsFromArray:((UIWindowScene *)scene).windows]; + } + if (windows.count > 0) { + return windows; + } +#ifndef IOS27_SDK_ALLOWED + BeginIgnoreDeprecatedWarning + NSArray *legacyWindows = self.windows; + EndIgnoreDeprecatedWarning + return legacyWindows ?: @[]; +#else + return @[]; +#endif +} + @end diff --git a/QMUIKit/UIKitExtensions/UIMenuController+QMUI.m b/QMUIKit/UIKitExtensions/UIMenuController+QMUI.m index 572dba84..c4c89cec 100644 --- a/QMUIKit/UIKitExtensions/UIMenuController+QMUI.m +++ b/QMUIKit/UIKitExtensions/UIMenuController+QMUI.m @@ -14,6 +14,7 @@ #import "UIMenuController+QMUI.h" #import "QMUICore.h" +#import "UIApplication+QMUI.h" #import "NSArray+QMUI.h" @implementation UIMenuController (QMUI) @@ -110,7 +111,7 @@ + (UIWindow *)qmuimc_menuControllerWindow { if (kMenuControllerWindow && !kMenuControllerWindow.hidden) { return kMenuControllerWindow; } - [UIApplication.sharedApplication.windows enumerateObjectsUsingBlock:^(__kindof UIWindow * _Nonnull window, NSUInteger idx, BOOL * _Nonnull stop) { + [UIApplication.sharedApplication.qmui_windows enumerateObjectsUsingBlock:^(__kindof UIWindow * _Nonnull window, NSUInteger idx, BOOL * _Nonnull stop) { NSString *windowString = [NSString stringWithFormat:@"UI%@%@", @"Text", @"EffectsWindow"]; if ([window isKindOfClass:NSClassFromString(windowString)] && !window.hidden) { if (@available(iOS 16.0, *)) { @@ -136,7 +137,7 @@ + (UIWindow *)qmuimc_menuControllerWindow { + (UIWindow *)qmuimc_firstResponderWindowExceptMainWindow { __block UIWindow *resultWindow = nil; - [UIApplication.sharedApplication.windows enumerateObjectsUsingBlock:^(__kindof UIWindow * _Nonnull window, NSUInteger idx, BOOL * _Nonnull stop) { + [UIApplication.sharedApplication.qmui_windows enumerateObjectsUsingBlock:^(__kindof UIWindow * _Nonnull window, NSUInteger idx, BOOL * _Nonnull stop) { if (window != UIApplication.sharedApplication.delegate.window) { UIResponder *responder = [UIMenuController qmuimc_findFirstResponderInView:window]; if (responder) { diff --git a/QMUIKit/UIKitExtensions/UIView+QMUI.m b/QMUIKit/UIKitExtensions/UIView+QMUI.m index faf17139..d0acc6b3 100644 --- a/QMUIKit/UIKitExtensions/UIView+QMUI.m +++ b/QMUIKit/UIKitExtensions/UIView+QMUI.m @@ -50,7 +50,7 @@ + (void)load { if (selfObject == firstArgv && [selfObject conformsToProtocol:@protocol(UITextInput)]) { // 像 QMUIModalPresentationViewController 那种以 window 的形式展示浮层,浮层里的输入框 becomeFirstResponder 的场景,[window makeKeyAndVisible] 被调用后,就会立即走到这里,但此时该 window 尚不是 keyWindow,所以这里延迟到下一个 runloop 里再去判断 dispatch_async(dispatch_get_main_queue(), ^{ - if (IS_DEBUG && ![selfObject isKindOfClass:[UIWindow class]] && selfObject.window && !selfObject.window.keyWindow) { + if (IS_DEBUG && ![selfObject isKindOfClass:[UIWindow class]] && selfObject.window && !selfObject.window.isKeyWindow) { [selfObject QMUISymbolicUIViewBecomeFirstResponderWithoutKeyWindow]; } }); diff --git a/QMUIKit/UIKitExtensions/UIWindow+QMUI.m b/QMUIKit/UIKitExtensions/UIWindow+QMUI.m index 57e03b66..3ec4cfed 100644 --- a/QMUIKit/UIKitExtensions/UIWindow+QMUI.m +++ b/QMUIKit/UIKitExtensions/UIWindow+QMUI.m @@ -14,6 +14,7 @@ // #import "UIWindow+QMUI.h" +#import "UIApplication+QMUI.h" #import "QMUICore.h" @implementation UIWindow (QMUI) @@ -98,12 +99,10 @@ - (void)qmuiw_hookIfNeeded { result = selfObject.qmui_canBecomeKeyWindow; } - BeginIgnoreDeprecatedWarning - UIWindow *keyWindow = UIApplication.sharedApplication.keyWindow; + UIWindow *keyWindow = UIApplication.sharedApplication.qmui_keyWindow; if (result && keyWindow && keyWindow != selfObject && keyWindow.qmui_canResignKeyWindowBlock) { result = keyWindow.qmui_canResignKeyWindowBlock(keyWindow, selfObject); } - EndIgnoreDeprecatedWarning return result; };