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
相关产品推荐
相关产品推荐

