Skip to content

iOS26 你们没有闪退吗?大佬啊,啥时候更新下库啊? #94

Description

@chenailuo
  • (UIView *)qmui_contentView {
    return [self valueForKeyPath:@"visualProvider.contentView"];
    }

这里会闪退的。
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<UIKit._UINavigationBarVisualProviderModernIOSSwift 0x11f9f8a00> valueForUndefinedKey:]: this class is not key value coding-compliant for the key contentView.'
*** First throw call stack:

Activity

  1. MrChen-Git commented on Dec 17, 2025

    @MrChen-Git

    同样也是有这个问题,应该不止这一处

  2. fanruoyang commented on Jan 20, 2026

    @fanruoyang

    这个问题 你后面如何处理了,我现在也遇到这种情况了

  3. Ambitiones commented on Mar 25, 2026

    @Ambitiones

    这是 iOS 26 后 nav 的contentView 变更导致 KVC 找不到的问题, 具体目前只能 fork 分支自己修改, 或者你可以临时修改, 找到pods 文件中的:
    `- (UIView *)qmui_contentView {
    return [self valueForKeyPath:@"visualProvider.contentView"];
    }

    将该方法修改为:

    • (UIView *)qmui_contentView {
      // return [self valueForKeyPath:@"visualProvider.contentView"];
      UIView *contentView = nil;
      if (@available(iOS 26.0, *)) {
      contentView = nil;
      } else {
      // 老版本走原来的方法,但是用 try 兜底
      @Try {
      contentView = [self valueForKeyPath:@"visualProvider.contentView"];
      } @catch (NSException *exception) {
      contentView = nil;
      }
      }
      if (contentView) {
      return contentView;
      }

       // 按类名查找 _UINavigationBarContentView
       Class class__NavigationBarContentView = NSClassFromString([NSString qmui_stringByConcat:@"_", @"UINavigationBar", @"ContentView", nil]);
       if (class__NavigationBarContentView) {
           contentView = [self subviewWithClass:class__NavigationBarContentView];
           if (contentView) {
               return contentView;
           }
       }
      
       // 按类名查找 UIKit.NavigationBarContentView
       Class class_UIKit_NavigationBarContentView = NSClassFromString(@"UIKit.NavigationBarContentView");
       if (class_UIKit_NavigationBarContentView) {
           contentView = [self subviewWithClass:class_UIKit_NavigationBarContentView];
           if (contentView) {
               return contentView;
           }
       }
      
       // 查找名字中包含 "ContentView" 的 view
       NSString *classNamePart_ContentView = @"ContentView";
       contentView = [self subviewWithClassNamePart:classNamePart_ContentView];
       if (contentView) {
           return contentView;
       }
      
       return nil;
      

      }

      • (UIView *)subviewWithClass:(Class)aClass {
        if (aClass) {
        for (UIView *sub in self.subviews) {
        if ([sub isKindOfClass:aClass]) {
        return sub;
        }
        // 有的系统层次里 contentView 不是直接子视图,尝试再向下查找一层
        for (UIView *sub2 in sub.subviews) {
        if ([sub2 isKindOfClass:aClass]) {
        return sub2;
        }
        }
        }
        }
        return nil;
        }
    • (UIView *)subviewWithClassNamePart:(NSString *)classNamePart {
      for (UIView *sub in self.subviews) {
      NSString *className = NSStringFromClass(sub.class);
      if ([className containsString:classNamePart]) {
      return sub;
      }
      for (UIView *sub2 in sub.subviews) {
      NSString *className2 = NSStringFromClass(sub2.class);
      if ([className2 containsString:classNamePart]) {
      return sub2;
      }
      }
      }
      return nil;
      }`
      重新运行即可

  4. douxindong commented on May 13, 2026

    @douxindong
    替换
    - (UIView *)qmui_contentView{...}的实现:
    ↓
    - (UIView *)qmui_contentView {
        // 优先尝试原始 KVC 方式(iOS 26 以下)
        if (@available(iOS 26.0, *)) {
            // iOS 26+ 不使用 KVC,走下面的兜底逻辑
        } else {
            @try {
                UIView *contentView = [self valueForKeyPath:@"visualProvider.contentView"];
                if (contentView) {
                    return contentView;
                }
            } @catch (NSException *exception) {
                // KVC 失败,继续走兜底逻辑
                NSLog(@"QMUI: Failed to get contentView via KVC: %@", exception);
            }
        }
        
        // iOS 26+ 或 KVC 失败时的兜底方案
        UIView *contentView = [self qmui_findContentView];
        if (contentView) {
            return contentView;
        }
        
        return nil;
    }
    
    #pragma mark - Private Helper Methods
    
    - (UIView *)qmui_findContentView {
        UIView *contentView = nil;
        
        // 1. 尝试 _UINavigationBarContentView(iOS 26 以下的老类名)
        Class contentViewClass = NSClassFromString(@"_UINavigationBarContentView");
        if (contentViewClass) {
            contentView = [self qmui_subviewWithClass:contentViewClass];
            if (contentView) return contentView;
        }
        
        // 2. 尝试 UIKit.NavigationBarContentView(Swift 风格的类名)
        contentViewClass = NSClassFromString(@"UIKit.NavigationBarContentView");
        if (contentViewClass) {
            contentView = [self qmui_subviewWithClass:contentViewClass];
            if (contentView) return contentView;
        }
        
        // 3. 模糊匹配类名中包含 "ContentView" 的视图
        contentView = [self qmui_subviewWithClassNamePart:@"ContentView"];
        if (contentView) return contentView;
        
        return nil;
    }
    
    - (UIView *)qmui_subviewWithClass:(Class)aClass {
        if (!aClass) return nil;
        
        for (UIView *subview in self.subviews) {
            if ([subview isKindOfClass:aClass]) {
                return subview;
            }
            // 某些系统版本中 contentView 不是直接子视图,需要向下查找一层
            for (UIView *subSubview in subview.subviews) {
                if ([subSubview isKindOfClass:aClass]) {
                    return subSubview;
                }
            }
        }
        return nil;
    }
    
    - (UIView *)qmui_subviewWithClassNamePart:(NSString *)classNamePart {
        if (!classNamePart.length) return nil;
        
        for (UIView *subview in self.subviews) {
            NSString *className = NSStringFromClass([subview class]);
            if ([className containsString:classNamePart]) {
                return subview;
            }
            for (UIView *subSubview in subview.subviews) {
                NSString *subClassName = NSStringFromClass([subSubview class]);
                if ([subClassName containsString:classNamePart]) {
                    return subSubview;
                }
            }
        }
        return nil;
    }
    
    @end
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions