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

Swift 3.2中UIControl addTarget方法的调用疑问

关于Swift中#selector跨类调用需显式类名的原因解析

我来帮你拆解清楚这个差异的核心——这完全是Swift类型安全机制升级带来的必然变化,你根本没有操作错误。

先搞懂新旧写法的本质区别

  • 旧版本的字符串写法:awesomeBtn.addTarget(nil, action:("awesomeMethod"), forControlEvents:.touchUpInside)
    这种方式是直接把方法名以字符串形式传给Objective-C运行时,属于纯动态调用。编译器在编译阶段不会做任何严格校验,只要运行时能找到同名方法就行,所以不管方法在哪个类里,只要名字对就能过编译。但这种写法风险极高,拼写错、方法改名后编译器不会提醒,只会在运行时崩溃。
  • 新版本的#selector语法:这是Swift专门引入的静态类型检查语法,编译器会在编译阶段就验证目标方法是否存在、是否符合Selector的签名要求,从根源上杜绝了字符串写法的运行时隐患。

为什么跨类时必须写类名?

当你在ClassA里写#selector(awesomeMethod)时,编译器会默认在当前上下文(也就是ClassA的作用域)里查找这个方法,所以如果方法就在ClassA里,能直接匹配到,自然不用额外指定。但如果方法在ClassB里,编译器在当前上下文找不到对应的方法,就必须你显式标注ClassB.awesomeMethod,告诉编译器去哪个类的作用域里找这个方法,这样才能完成静态校验,确保这个方法确实存在且符合要求。

额外提一句

#selector的设计初衷就是把Objective-C的Selector机制和Swift的类型安全特性结合起来,既保留了Selector的动态能力,又通过编译时检查避免了字符串写法的各种坑。你遇到的情况完全是正常的语言设计逻辑,放心用就好。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:23:15