Swift 3未遵循协议可调用协议方法,Swift 4为何崩溃?
为什么Swift 3正常运行,Swift 4却崩溃?
这个问题的核心是Swift 3和Swift 4在**@objc方法推断以及Objective-C协议兼容性**上的行为差异,我来给你详细拆解:
Swift 3的宽松兼容逻辑
- 当你的ViewController继承自
UIViewController(它本身是NSObject子类),在Swift 3中,只要你实现了UITableViewDataSource/UITableViewDelegate的方法,编译器会隐式地给这些方法添加@objc标记,同时让你的类在Objective-C运行时层面“兼容”这些协议。 - Storyboard是通过Objective-C运行时来绑定tableView的dataSource和delegate的,运行时会通过方法签名去查找对应的实现。因为Swift 3自动帮你把方法暴露给了Objective-C,所以即使你没显式写
遵循协议,运行时也能找到方法,自然不会崩溃。
Swift 4的严格化规则
- Swift 4对@objc推断做了大幅收紧:默认情况下,
NSObject子类中的方法不会自动被标记为@objc,只有满足以下情况才会自动添加:- 类显式遵循了Objective-C协议(比如
UITableViewDataSource) - 方法是重写父类的@objc方法
- 你手动给方法加上了
@objc标记
- 类显式遵循了Objective-C协议(比如
- 如果你没显式声明遵循协议,那么你写的那些代理方法(比如
tableView(_:numberOfRowsInSection:))不会被自动标记为@objc。当Storyboard通过Objective-C运行时尝试调用这些方法时,会找不到对应的实现,直接触发unrecognized selector sent to instance的崩溃——这就是你遇到的问题。
为什么Swift团队要做这个改变?
主要是为了性能优化:@objc方法会带来额外的运行时开销,Swift 4希望减少不必要的Objective-C交互,让代码更贴近Swift原生的特性,只有在明确需要和Objective-C(比如Storyboard、OC框架)交互时,才暴露方法给OC运行时。
快速解决方法
- 最规范也最简单的方式:在ViewController的类声明里显式添加协议遵循,比如:
这样编译器会自动给所有协议要求的方法加上@objc标记,运行时就能正常找到方法了。class MyTableVC: UIViewController, UITableViewDataSource, UITableViewDelegate { // 你的实现代码 } - 如果你不想显式遵循协议(不推荐),也可以给每个代理方法手动加上
@objc标记,但这样容易遗漏,维护成本更高。
内容的提问来源于stack exchange,提问作者Kiah_Dev
相关产品推荐
相关产品推荐

