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

Swift中能否用#selector指向带参数的静态函数?

在Swift中用#selector指向带参数的静态函数

当然可以实现!不过你肯定是漏掉了几个关键步骤,才会碰到这个编译错误——我之前也踩过类似的坑,给你梳理一下正确的姿势:

核心原因:#selector依赖Objective-C运行时

报错提示argument of '#selector' does not refer to an '@objc' method,本质是因为#selector只能识别暴露给Objective-C运行时的方法。Swift的静态函数(类方法)默认不会被Obj-C识别,必须满足两个前提:

  • 所在类继承自NSObject(或者用@objcMembers标记类,不过继承NSObject是更常规的做法)
  • 静态函数本身标记@objc

正确的实现示例

第一步:定义符合要求的带参数静态函数

class MyUtilityClass: NSObject {
    // 带参数的静态类方法,必须标记@objc,且参数类型要兼容Obj-C
    @objc static func handleAction(with input: String) {
        print("处理参数:\(input)")
    }
}

这里要注意:

  • 类必须继承NSObject,否则@objc标记无法生效
  • 参数类型比如String、Int都是Obj-C支持的,如果用Swift独有的类型(比如自定义无@objc标记的枚举/结构体),会导致方法无法被Obj-C识别

第二步:正确使用#selector引用

当你需要在按钮点击、定时器等场景调用这个静态函数时,要注意方法签名必须包含参数对应的冒号:

let testButton = UIButton(type: .system)
// #selector里要写出带参数占位符的方法名,对应Objective-C的方法签名
testButton.addTarget(nil, action: #selector(MyUtilityClass.handleAction(with:)), for: .touchUpInside)

为什么要加冒号?因为Objective-C的方法签名中,冒号代表参数的位置——一个参数对应一个冒号,多个参数就要依次添加(比如func doSomething(with a: String, and b: Int)对应的selector是#selector(doSomething(with:and:)))

常见坑点避坑

  • 忘记标记@objc:这是最常见的原因,直接导致方法无法被Obj-C运行时识别
  • 类未继承NSObject:即使加了@objc,非NSObject子类的方法也无法被Obj-C访问
  • 方法签名写错:比如漏写参数对应的冒号,#selector会找不到对应方法
  • 参数类型不兼容:用Swift独有的类型作为参数,会导致@objc标记失效

按照上面的步骤调整后,你的代码应该就能正常编译运行了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 04:14:08