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; } 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"]; }