You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UIMenuController在macOS Monterey系统触发时崩溃的问题咨询

问题根因

这是macOS 12.x版本运行「设计为iPad」iOS应用时的系统原生bug:UIKitMacHelper框架在将UIMenuController的菜单项转换为 macOS 原生NSMenuItem时,部分系统自动生成的菜单项title属性为nil,向可变字典插入空值时触发了NSInvalidArgumentException异常。该问题在macOS 13及以上版本已经被官方修复,仅影响macOS 12.x系统。

可用规避方案

以下方案按实现成本从低到高排序:

  • 方案1:禁用macOS环境下的右键触发逻辑
    仅保留iOS原生的长按唤起菜单逻辑,拦截右键手势即可避免触发该bug:
    - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
        if (@available(iOS 14.0, *)) {
            // 判断是否运行在Apple硅Mac的iOS应用环境
            if ([NSProcessInfo processInfo].isiOSAppOnMac && NSProcessInfo.processInfo.operatingSystemVersion.majorVersion == 12) {
                // 拦截右键点击手势
                if ([gestureRecognizer isKindOfClass:NSClassFromString(@"UIContextMenuInteractionClickPresentationGestureRecognizer")]) {
                    return NO;
                }
            }
        }
        return [super gestureRecognizerShouldBegin:gestureRecognizer];
    }
    
  • 方案2:完全自定义UIMenuController菜单项
    不使用系统默认生成的复制、粘贴等菜单项,手动构造所有需要的菜单项,显式指定非空的title:
    UIMenuItem *copyItem = [[UIMenuItem alloc] initWithTitle:@"复制" action:@selector(customCopyAction:)];
    UIMenuItem *pasteItem = [[UIMenuItem alloc] initWithTitle:@"粘贴" action:@selector(customPasteAction:)];
    UIMenuController.sharedMenuController.menuItems = @[copyItem, pasteItem];
    
  • 方案3:Runtime兜底修复
    不想修改原有菜单逻辑的话,可以通过runtime交换方法,拦截空title的场景补默认值,从根源避免崩溃:
    #import <objc/runtime.h>
    
    @implementation MacOS12MenuFix
    + (void)load {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            if (@available(iOS 14.0, *)) {
                // 仅在macOS 12的iOS应用环境下生效
                if (![NSProcessInfo processInfo].isiOSAppOnMac || NSProcessInfo.processInfo.operatingSystemVersion.majorVersion != 12) {
                    return;
                }
                Class targetClass = NSClassFromString(@"_UIMenuBarItem");
                SEL originalSel = NSSelectorFromString(@"properties");
                SEL fixSel = @selector(fix_properties);
                Method originalMethod = class_getInstanceMethod(targetClass, originalSel);
                Method fixMethod = class_getInstanceMethod(self, fixSel);
                if (originalMethod && fixMethod) {
                    method_exchangeImplementations(originalMethod, fixMethod);
                }
            }
        });
    }
    - (NSDictionary *)fix_properties {
        NSDictionary *origin = [self fix_properties];
        NSMutableDictionary *mutable = origin.mutableCopy;
        if (!mutable[@"title"]) {
            mutable[@"title"] = @"";
        }
        return mutable.copy;
    }
    @end
    

内容的提问来源于stack exchange,提问作者Vlad Grigorov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 13:24:01