![iOS开发:从零基础到精通](https://wfqqreader-1252317822.image.myqcloud.com/cover/796/26793796/b_26793796.jpg)
5.3 协议
5.3.1 协议简介
协议(Protocol)是多个类共享的一个方法列表,在协议中列出的方法,在定义协议的类中并没有给出具体的实现,而协议的实现的功能是在遵守协议的类中定义的。通过协议可以实现对象之间的通信,同时又能够使类的定义更加通用。也就是说,遵守同一协议的类,针对协议中定义的方法,可以在类中实现不同的功能。例如,当一个视图View类的对象被单击时,在不同的控制器Controller类中可以定义不同的响应方法。
1.为什么需要协议
协议用来解决对象之间通信问题,特别是当视图类对象向控制器类对象通信(发送用户点击动作、请求设置视图数据)时,常使用协议。通过协议可以进一步提升该类的通用性,例如,对于某个按钮的点击动作,在所有遵守协议的对象中,可以定义不同的动作。
2.协议的种类
协议,可以理解为日常生活中的“合同”。可以存在多种合同,如租房合同、销售合同,当甲乙双方签订某个合同时,意味着对双方的行为有了约束。另外,即便是同一类合同,针对不同的人,虽然合同模板相同,但具体的条款可能不同,例如,劳动合同是一个统一的模板,单位和劳动者都要遵守,但是其中的诸如薪资、试用期、合同年限等条款,可以因人而异。在iOS开发中,可以定义各种各样的协议,常见的有代理协议、数据源协议等。
3.协议的实现步骤
协议的实现相对复杂,但步骤都是统一的。当需要实现协议时,可以按照如下的步骤一步步添加相关的代码,总体来说包括3个核心步骤:
- 添加协议,并设置协议中包含的方法,同时添加一个属性用于设置遵守协议的对象。
- 设置触发执行协议中方法的时机,例如发生了用户点击事件。
- 在遵守协议的类中,实现协议中方法的具体功能。
5.3.2 代理
1.代理协议
在iOS开发中,经常使用到代理(Delegate)协议以及数据源协议。所谓代理协议,通俗来讲,就是委托别人办事。例如,用户单击了一个子控件上的按钮,这时可以委托控制器去处理一些事物或实现一些功能,例如切换到新的控制器或者发送一个网络请求等。代理协议也是协议,因此实现自定义代理协议的方法与协议的实现,基本一致。
2.代理协议的实现
下方的示例代码中实现了在一个UIView视图类中实现代理协议,并在其中添加了一个代理协议方法,当用户发生点击操作时会执行遵守该代理协议对象中实现的协议方法。
- 在自定义视图类MYView.h文件中:设置类引用@class、定义代理协议名称、定义代理协议中包含的方法、添加代理属性(注意使用weak属性)。
注意:协议中的方法,一般情况下(不强制),通常第一个参数都是对象自身,这样做的好处在于,在遵守协议的类中实现协议中的方法时,可以获取一些有用数据。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T139_16545.jpg?sign=1739270574-SIdxHJcxvR0O5IdwX88OofWifcMU1ZT5-0-4b2130a3424c1aaaaa9794761ab6736d)
- 在MYView.m文件中,监听代理协议定义事件的发生。当事件发生时,通知遵守代理协议的对象(如控制器)去工作,即设置在实现代理协议的类中,代理协议方法执行的时机。
注意:我们在通知遵守代理协议的对象(self.delegate)调用协议方法之前,通常会先判断一下该对象中是否已经实现了该协议方法,即是否响应代理协议方法对应的消息,使用respondsToSelector:方法。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T139_16547.jpg?sign=1739270574-R9l4KI6b4fTbhBIsLGv8NyQ1voYd2kbz-0-490da6139a5378a462fb923081ad8ee6)
- 在需要遵守代理协议的类中,引用头文件并遵守代理协议,遵守代理协议需要在类的接口部分使用<>符号来声明该类需要遵守的协议,同一个类可以遵守多个协议。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T140_16675.jpg?sign=1739270574-IrfqjlDWqAOC3KWNGOOcDRh6zWR9Npm6-0-21757100cbe2332c0d6420a78713d6b3)
- 设置代理对象。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T140_82852.jpg?sign=1739270574-OzZanjfMpx5mw3ehHHh9UBKm0zpxn0BY-0-be7077b418d948edc2757f985ba6075e)
- 实现协议方法。即当触发条件发生时,执行的动作。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-T140_16680.jpg?sign=1739270574-eXScqpeYWoyVzblsCF35b9Y15Z2AAis8-0-55c4daecf080be008d573debd7eec025)
运行结果如图5-15所示。当点击屏幕上面红色的视图对象时,会打印如下的日志。通过日志可以看到,当点击视图对象时,调用的是控制器类中实现的代理协议,同时,视图对象可以传递信息(message)给控制器对象,从而实现了对象之间的通信。
![](https://epubservercos.yuewen.com/D4B438/15253388904120706/epubprivate/OEBPS/Images/Figure-P140_16682.jpg?sign=1739270574-44i0h2nA6UCE4dyB4BifYR0sbWtJQZtj-0-aa5348375a3d5542b91f6a57e69030d2)
图5-15 运行结果