为何使用extension时无需为ViewController添加UIScrollViewDelegate协议?
这问题我当初刚接触Swift协议扩展的时候也踩过坑,给你掰扯清楚哈~
为什么两种写法结果不同?
写法一报错的原因
你在ViewController的类声明里已经明确标注了遵循UIScrollViewDelegate:
class ViewController: UIViewController, UIScrollViewDelegate { ...... }
之后又在extension里再次声明遵循同一个协议:
extension ViewController: UIScrollViewDelegate { // Error: Redundant conformance... }
这属于重复协议遵循,Swift编译器会直接报错——一个类只需要声明一次遵循某个协议,不管是在类本体还是extension中,重复声明完全多余,所以编译器会提示你“Redundant conformance”。
写法二无报错的原因
写法二中类本体只继承了UIViewController,没有声明任何额外协议:
class ViewController: UIViewController { ...... }
然后在extension里声明遵循UIScrollViewDelegate,这是Swift完全允许的写法。Swift支持将协议的遵循和实现拆分到extension中,甚至可以把不同协议的实现分到不同extension里,这样能让代码结构更清晰,也是官方推荐的写法之一。
UIViewController本身是否遵循UIScrollViewDelegate?
答案是不遵循。你可以简单验证:如果UIViewController默认遵循该协议,那你直接实现scrollViewDidScroll这类代理方法时,编译器不会有任何提示,但实际情况是,如果你不手动声明遵循UIScrollViewDelegate,编译器会提示你“Instance method 'scrollViewDidScroll' nearly matches optional requirement of protocol 'UIScrollViewDelegate'”,这就说明UIViewController本身并没有默认遵循这个协议。
写法二之所以可行,是因为extension的作用就是给已有的类型添加协议遵循和实现,只要类本体没声明过该协议,extension里的声明就合法,编译器会自动把类本体和extension的内容合并,视为这个类确实遵循了协议。
内容的提问来源于stack exchange,提问作者John

