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

Cocoa 如何通过代码为ScrollView/CollectionView添加contextMenu右键菜单

修复CollectionView/ScrollView右键菜单不弹出问题

核心问题

你当前代码只定义了菜单实体,没有完成两个核心配置:

  • 没有把自定义NSMenu绑定到目标视图的menu属性,AppKit中所有视图要显示右键菜单必须显式赋值menu属性
  • 没有处理右键点击时的选中逻辑,菜单弹出时无法正确获取到你点击位置对应的患者数据

修复步骤

  1. 绑定菜单到目标视图
    在viewDidLoad或视图初始化的生命周期方法中,给你的CollectionView/ScrollView赋值菜单:
override func viewDidLoad() {
    super.viewDidLoad()
    // 其他原有初始化代码
    
    // 给CollectionView加菜单
    collectionView.menu = contextMenu
    // 如果是给ScrollView加菜单,使用下一行代码
    // scrollView.menu = contextMenu
}
  1. 实现菜单弹出前的选中逻辑
    首先给自定义菜单设置代理,在contextMenu的定义中新增代理赋值:
private var contextMenu: NSMenu {
    let rightClickMenu = NSMenu()
    rightClickMenu.delegate = self // 新增这行
    
    // 原有菜单项代码保持不变
    let editPatientItem = NSMenuItem()
    editPatientItem.title = LocalizationUtility.localizedString("contextMenu.editPatientInfo")
    editPatientItem.target = self
    editPatientItem.action = #selector(didSelectContextItem(_ :))
    editPatientItem.tag = 1
    
    rightClickMenu.addItem(editPatientItem)
    return rightClickMenu
}

然后让你的ViewController遵守NSMenuDelegate协议,实现菜单即将弹出的代理方法,获取右键点击位置对应的患者数据:

// 替换YourViewController为你当前的控制器类名
extension YourViewController: NSMenuDelegate {
    func menuWillOpen(_ menu: NSMenu) {
        guard let currentEvent = NSApp.currentEvent,
              let targetCollectionView = self.collectionView else {
            selectedPatients = []
            return
        }
        // 将点击位置转换为CollectionView坐标系下的点
        let clickPosition = targetCollectionView.convert(currentEvent.locationInWindow, from: nil)
        // 获取点击位置对应的单元格索引
        if let clickIndexPath = targetCollectionView.indexPathForItem(at: clickPosition) {
            // 替换dataSourceArray为你CollectionView绑定的原始患者数据源数组
            selectedPatients = [dataSourceArray[clickIndexPath.item]]
            // 可选:右键点击时自动选中对应单元格,增加视觉反馈
            targetCollectionView.selectItems(at: [clickIndexPath], scrollPosition: [])
            menu.item(withTag: 1)?.isEnabled = true
        } else {
            // 点击空白区域时清空选中,禁用编辑菜单项
            selectedPatients = []
            menu.item(withTag: 1)?.isEnabled = false
        }
    }
}

额外校验点

如果修改后仍不生效,检查以下配置:

  • 目标CollectionView/ScrollView的isEnabled属性为true,没有被禁用交互
  • 菜单项的action方法没有拼写错误,@objc标记正常
  • 如果你是嵌套的ScrollView,确保菜单绑定到了最上层响应交互的视图上

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 05:54:04