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

Swift:如何为#selector传递参数?解决传参报错问题

解决Swift中UIMenuItem selector传参报错问题

你遇到的错误核心原因是:#selector只能引用符合Objective-C签名的方法,不能直接在选择器里传递参数(比如你写的#selector(setDevice(deviceId: device.uniqueID))这种写法完全不合法)。另外UIKeyCommand的action方法有固定签名要求,必须接收一个UIKeyCommand类型的sender参数。

解决步骤

  • 调整setDevice方法的签名,让它接收sender参数,从sender的userInfo中提取设备ID
  • 创建UIKeyCommand时,通过propertyList(对应userInfo)传递uniqueID
  • 修复循环中重复创建菜单的问题(原代码会在每次循环插入新菜单,导致重复添加)

修正后的完整代码

override func buildMenu(with builder: UIMenuBuilder) {
    super.buildMenu(with: builder)
    
    // 先收集所有设备对应的菜单项
    var menuItems: [UIKeyCommand] = []
    ReactNativeMidiKit().midiManager.endpoints.outputs.forEach { device in
        let menuItem = UIKeyCommand(
            title: device.name,
            action: #selector(setDevice(_:)),
            input: nil,
            modifierFlags: [],
            propertyList: ["deviceId": device.uniqueID]
        )
        menuItem.state = device.uniqueID == selectedUniqueID ? .on : .off
        menuItems.append(menuItem)
    }
    
    // 一次性创建顶级菜单并插入
    let midiDeviceMenu = UIMenu(title: "Midi Devices", children: menuItems)
    builder.insertSibling(midiDeviceMenu, afterMenu: .application)
}

@objc
func setDevice(_ sender: UIKeyCommand) {
    guard let deviceId = sender.userInfo?["deviceId"] else {
        return
    }
    print(deviceId)
    // 这里添加设备切换的业务逻辑
    selectedUniqueID = deviceId as? String // 假设selectedUniqueID是你存储选中ID的变量
    UIMenuSystem.main.setNeedsRebuild()
}

关键改动说明

  1. 方法签名调整:把原setDevice(deviceId: Any)改成@objc func setDevice(_ sender: UIKeyCommand),完全符合UIKeyCommand的action方法要求
  2. 参数传递方式:通过UIKeyCommand的propertyList字段存入设备ID,在方法内从sender.userInfo中取出
  3. 菜单创建逻辑优化:原代码在循环中重复创建并插入顶级菜单,现在先收集所有菜单项,再一次性创建菜单,避免重复添加

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 18:40:33