Swift 5.2中@objc无返回值函数自动补全显示删除线问题咨询
关于UIRefreshControl #selector中函数显示删除线的原因解析
嘿,这个现象其实是Xcode的代码提示逻辑和UIKit的Target-Action机制历史兼容细节共同导致的,我来给你理清楚:
1. UIKit Target-Action的签名历史
在Objective-C时代,UIControl(UIRefreshControl的父类)的action方法其实推荐带有返回值(通常是BOOL类型),用来决定是否继续传递事件到下一个响应者。不过很多控件(比如UIRefreshControl)本身并不关心这个返回值,所以无返回值的void方法也能正常触发——这是UIKit做的兼容处理。
2. Swift与Objective-C桥接的提示逻辑
当你用@objc标记一个无返回值的Swift函数时,它会被桥接成Objective-C的void方法。Xcode的代码补全系统会检测到这个方法和UIControl期望的“推荐action签名”不匹配,所以给它加上删除线,提示你“这不是最符合API设计的写法”——但这绝对不是方法被废弃,只是一个风格提示,所以程序运行完全正常。
3. 为什么加返回值就消除了删除线
当你给refresh_B加上Bool返回值后,它桥接成的Objective-C方法签名就变成了:
- (BOOL)refresh_B:(UIRefreshControl *)sender;
这个签名完全匹配UIControl期望的action方法格式,Xcode就认为这是“正确”的写法,删除线自然就消失了。而因为UIRefreshControl根本不会去读取这个返回值,所以你返回true还是false对功能没有任何影响。
补充说明
- 这个删除线只是Xcode的代码提示,不影响编译和运行,如果你觉得看着别扭,要么加个返回值(像你做的那样),要么直接忽略它也没问题。
- 除了加返回值,你也可以通过
@objc重命名方法来规避提示,但完全没必要——加个返回值是最简单的解决方案。
附上你的最小复现代码,方便对应:
let refreshControl_A = UIRefreshControl() let refreshControl_B = UIRefreshControl() override func viewDidLoad() { super.viewDidLoad() refreshControl_A.addTarget(self, action: #selector(refresh_A(sender:)), for: .valueChanged) refreshControl_B.addTarget(self, action: #selector(refresh_B(sender:)), for: .valueChanged) } @objc func refresh_A(sender: UIRefreshControl) { print("Have strikethrough!") } @objc func refresh_B(sender: UIRefreshControl) -> Bool { print("No strikethrough!") return true }
内容的提问来源于stack exchange,提问作者唐梓皓
相关产品推荐
相关产品推荐

