Objective-C官方文档 协议
版权声明:原创作品,谢绝转载!否则将追究法律责任。
在现实生活中,当处理某一情况的时候人们往往遵循严格的程序。执法人员他们在打官司的收集证据和询问的时候一定要遵守协议。
在面向对象的语言中,最重要的是一个对象需要定义一些行为在某种情况下。例如:一个tableView希望能够和数据源交互目的是为了表明他要展示什么数据。这意味着数据必须回应tableView一组特殊的消息。
这个数据源可能是一些类的实例,例如一个Controller或者一个专门继承NSObject类的数据源类为了让tableView知道这个对象适不适合做这个数据源,所以必须声明的是让这个对象实现必须的方法。
Objective-c允许你定义协议,表明这个方法希望用在特殊的情况。这章的主要内容描述了定义一个标准协议的语法,并且声明一个类接口来遵守这个协议,这意味着这个类必须实现他需要实现的方法。
协议定义消息传递的规则:
一个类的接口声明了和这个类关联的属性和方法。协议和之前定义类接口相比,被用来声明方法和属性是为了一些特定的类。
声明协议的基本语法:
@protocol ProtocolName
// list of methods and properties
@end
协议可以包含类方法实例方法和属性的声明:
例如一个自定义View类用来展示饼状图如下图:

为了使这个View可能的重复利用,所有的决策信息应该留给另一个对象,一个数据源。这意味着多个实例相同的视图类,可能展示不同的信息通过和不同的数据源进行交互。
这个最低的信息需要包括这个饼图包含几个部分,每个部分的相对大小,并且每个部分的标题。因此这个饼图的协议方法大概包含以下几个不分:
@protocol XYZPieChartViewDataSource
- (NSUInteger)numberOfSegments;
- (CGFloat)sizeOfSegmentAtIndex:(NSUInteger)segmentIndex;
- (NSString *)titleForSegmentAtIndex:(NSUInteger)segmentIndex;
@end
注意:这个协议用无符号整形来定义标量值,后面章节会详细讨论。
这个饼图视图类将要需要一个属性来跟踪数据源对象。这个对象可以是任何类,因此这个属性的类型是id类型。唯一知道这个对象的信息是他符合相关的协议。
这个在View里面定义数据源的属性像这样:
@interface XYZPieChartView : UIView
@property (weak) id <XYZPieChartViewDataSource> dataSource;
...
@end
Objective-c用尖括号表示符合这个协议。这个例子声明了一个弱引用类型通用类型的对象指针并且符合XYZPieChartViewDataSource。
注意:代理和数据源的属性被声明弱引用类型的原因是避免强引用的循环。
通过给属性指定相关的协议,你将要得到一个警告如果你设置的这个对象的属性不符合这个协议,尽管这个属性的类型是通用类型的。不要担心这个实例对象是UIViewController还是NSObject。最重要的是他符合这个协议,意味着这个饼图知道他可以请求需要的数据。
协议可以有可选的方法:
默认情况下协议声明下的方法都是必须实现的方法。这意味着任何类遵守这个协议必须实现他的这些方法。
你也可以声明可选的方法在协议里面。这些方法是某些类选择实现的。
例如你可以决定这个显示饼图标题的这个协议方法是可选的。如果这个数据源对象不实现这个可选的方法。那么就没有标题显示在饼图上。我们可以如下声明可选的协议方法:
@protocol XYZPieChartViewDataSource
- (NSUInteger)numberOfSegments;
- (CGFloat)sizeOfSegmentAtIndex:(NSUInteger)segmentIndex;
@optional
- (NSString *)titleForSegmentAtIndex:(NSUInteger)segmentIndex;
@end
在这个例子中只有后面这个方法是可选的。之前的那些方法没有说明因此默认还是必须实现的。
这个@optional指令适合任何方法遵循他,要么直到最后协议的定义,或者到另一个指令的声明例如@required例如:
@protocol XYZPieChartViewDataSource
- (NSUInteger)numberOfSegments;
- (CGFloat)sizeOfSegmentAtIndex:(NSUInteger)segmentIndex;
@optional
- (NSString *)titleForSegmentAtIndex:(NSUInteger)segmentIndex;
- (BOOL)shouldExplodeSegmentAtIndex:(NSUInteger)segmentIndex;
@required
- (UIColor *)colorForSegmentAtIndex:(NSUInteger)segmentIndex;
@end
这个例子定义了三个必须实现的方法还有两个可选的方法。
确保可选方法是在运行时被实现的:
如果这个协议方法是可选的你必须检查这个对象是否实现了这个方法再调用他。例如:这个饼图可能这样测试这个方法:
NSString *thisSegmentTitle;
if ([self.dataSource respondsToSelector:@selector(titleForSegmentAtIndex:)]) {
thisSegmentTitle = [self.dataSource titleForSegmentAtIndex:index];
}
这个respondsToSelector:方法使用一个选择器,他指的是一个方法编译后的标识符,你能提供正确的标识符通过使用@selector()指令和指定的方法名称。
如果这个数据源在这个例子中实现这个方法,这个标题就出现,否则这个标题是空的。
注意:局部变量默认初始化为nil。
如果你试图调用了未定义在特殊协议里面的方法,那么你就会得到一个恶错误。为了避免这个编译错误你需要设置你的自定义协议采用NSObject协议。
协议是可以继承其他的协议的:
就像一个Objective-c类可以继承其他的父类一样,你可以指定一个协议符合另一个协议。
例如一个最好的实践定义你的协议符合NSObject协议(一些NSObject行为从其类接口中分离到一个单独的协议文件里)NSObject类是采用NSObject协议的。
通过表明你自己的协议符合NSObject的协议来表明任何对象采用自定义协议还将提供NSObject协议的方法。因为你可能用NSObject的一些子类,你不要为这些NSObject协议方法提供实现而担心。该协议提供是有用的就像上面描述的那样。
指定一个协议符合另一个协议,你需要在尖括号里提供另一个协议的名字就像这样:
@protocol MyProtocol <NSObject>
...
@end
在这个例子中任何采用自定义协议同样也能使用NSObject协议的方法。
符合协议:
声明一个类符合协议需要在尖括号里写上协议的名字像这样:
@interface MyClass : NSObject <MyProtocol>
...
@end
这意味着MyClass的实例不仅仅能响应自己在接口定义的方法,而且这个MyClass也提供在myProtocol必选的方法的实现。没有必要重新声明这些方法在接口文件里,采用协议是足够的。
如果你需要一个类采用多个协议,你可以指定他们作为一个以逗号分隔的列表像这样:
@interface MyClass : NSObject <MyProtocol, AnotherProtocol, YetAnotherProtocol>
...
@end
技巧:如果发现你自己符合了很多协议在类里面,这可能意味着你可能需要重构那些过去复杂的类,分裂了必须的行为在很多小类,每个都有清晰的责任。
一个相对新的OSX操作系统普遍存在的缺陷和IOS开发是使用一个应用程序委托类包含大多数应用程序的功能(管理底层数据结构,服务数据到多个用户界面元素,以及响应手势和其他用户交互)。随着复杂性的增加,类变的更难维护。
一旦你已经声明符合某个协议,这个类必须最少提供协议要必须实现方法的实现,以及任何你选的可选方法,这个编译器将要警告你如果你没有实现必须实现的方法。
注意:这个定义在协议里面的方法就像定义在接口里面的方法一样。这个方法的名字和参数类型在实现的时候必须和在协议里面定义的一样。
cocoa和cocoa touch定义了大量的协议
协议被cocoa和cocoatouch对象在很多不同的环境中使用。例如,tableView类即用数据源对象来提供他需要的信息。也定义了自己的数据源协议。tableView的类允许你设置委托对象,必须符合UITableViewDelegate协议,这个代理的责任负责处理用户交互或者定制显示的某些条目。
一些协议用于表示类之间的相似性。而不是与特定类的需求,一些协议相反与更普遍的cocoa或者cocoa touch沟通联系机制,可以采用多个不相关的类。
例如一些框架数据对象像集合对象NSArray和NSDictionay支持NSCoding协议,这意味着他可以编解码给他们的属性为了存档或者发布作为原始数据。NSCoding使把对象写入磁盘变的更容易,这些对象符合这个协议。
一些Objective-c的低级特性也依靠协议。为了使用快速枚举,例如,一个集合必须符合NSFastEnumeration协议,就像在Fast Enumeration Makes it East to Enumerate a Collection。此外,一些对象可以被copy,例如当用属性的copy关键字的时候,这些对象必须符合NSCopying协议,否则你将要在运行时得到一个异常。
协议都是匿名的
协议也可以在对象不确定的情况使用,或者需要隐藏。
例如一个框架的开发者可能选择不公布某些类的接口。因为这些类名字不知道,用这个框架的人不可能直接创建这个类的实例。相反的一些在框架的对象被典型的设计为返回一个创建好的实例对象。像这样:
id utility = [frameworkObject anonymousUtility];
为了使anonymousUtility对象更有用,这个框架开发者公布了协议的某些方法。尽管原始类的接口没有被提供。这意味着类保持匿名,对象仍然可以被使用在一个有限的方式:
id <XYZFrameworkUtility> utility = [frameworkObject anonymousUtility];
如果你写IOS的应用用core Data框架,例如你可能会遇到NSFetchedResultsController类。这个类帮助datasource对象为tableView提供存储数据,使他更容易提供行数的信息。
如果你能用到tableView的多个分区,你也可以得到一些分区信息的结果。而不是返回一个特定的类包含分区信息,NSFetchedResultsController返回一个匿名对象,这个匿名对象符合NSFetchedResultsSectionInfo协议。这意味着他仍然可以查询对象为你需要的信息,比如一个分区多少行:
NSInteger sectionNumber = ...
id <NSFetchedResultsSectionInfo> sectionInfo =
[self.fetchedResultsController.sections objectAtIndex:sectionNumber];
NSInteger numberOfRowsInSection = [sectionInfo numberOfObjects];
尽管你不知道sectionInfo 对象,NSFetchedResultsSectionInfo 协议表明他仍然可以响应numberOfObjects方法。
Objective-C官方文档 协议的更多相关文章
- gRPC官方文档(通讯协议)
文章来自gRPC 官方文档中文版 HTTP2 协议上的 gRPC 本文档作为 gRPC 在 HTTP2 草案17框架上的实现的详细描述,假设你已经熟悉 HTTP2 的规范.产品规则采用的是ABNF 语 ...
- Spring 4 官方文档学习 Spring与Java EE技术的集成
本部分覆盖了以下内容: Chapter 28, Remoting and web services using Spring -- 使用Spring进行远程和web服务 Chapter 29, Ent ...
- Spring 4 官方文档学习(十四)WebSocket支持
个人提示:如果需要用到页面推送,高频且要低延迟,WebSocket无疑是最佳选择.否则还是轮询和long polling吧. 做了一个小demo放在码云上,有兴趣的可以看一下,简单易懂:websock ...
- OC-苹果官方文档
苹果官方文档 help>documentation>左边iOS>language>objective>the objective-c programming langua ...
- clang format 官方文档自定义参数介绍(中英文)
官方文档:http://clang.llvm.org/docs/ClangFormatStyleOptions.html 中文 在代码中配置样式 当使用 clang::format::reformat ...
- 自己翻译 delegation 官方文档
什么是代理,知道怎么用,见过N次.会用代理传值,还不够.代理到底是用来干嘛的嘛?还是看看官方文档吧,自己翻译出来看看是不是通顺 代理: 代理是一个简单高效的模式,尤其是一个类在编程的过程中代表或者需要 ...
- spring官方文档中文版
转 http://blog.csdn.net/tangtong1/article/details/51326887 spring官方文档:http://docs.spring.io/spring/do ...
- ios学习笔记第四天之官方文档总结
start developing ios app today. 官方文档的体系结构为: 各层的主要框架图: objectice-c是动态语言 Objective-C 为 ANSI C 添加了下述语法和 ...
- Spring Cloud官方文档中文版-服务发现:Eureka服务端
官方文档地址为:http://cloud.spring.io/spring-cloud-static/Dalston.SR3/#spring-cloud-eureka-server 文中例子我做了一些 ...
随机推荐
- Swing AWT一套新的图形界面系统
Swing 是在AWT的基础上构建的一套新的图形界面系统,它提供了AWT 所能够提供的所有功能,并且用纯粹的Java代码对AWT 的功能进行了大幅度的扩充. 例如说并不是所有的操作系统都提供了对树形控 ...
- (转) 解密H264、AAC硬件解码的关键扩展数据处理
出自:http://blog.itpub.net/30168498/viewspace-1576794/ 通过上一篇文章,我们用ffmpeg分离出一个多媒体容器中的音视频数据,但是很可能这 ...
- Linux SD卡驱动开发(四) —— SD 控制器之真正的硬件操作
前面对SD卡控制器有了一个主要的介绍.事实上SD控制器层更过的意义是为core层提供一种操作SD卡硬件的一种方法.当然不同的控制器对硬件控制的方法不尽同样,可是他们终于都能像core层提交一个统一的封 ...
- C# 分享几个ip的方法吧,包括正则验证ip
/// <summary> /// 正规则试验IP地址 /// </summary> /// <param name="IP"></par ...
- 设置时间同步(Linux,Solaris)
经过网上各种搜索,将LINUX平台及solaris平台的时间同步整理如下: 主机情况:应用:2台LINUX服务器 redhat 5.5 内网数据库:2台Solaris服务器 Solaris 10 内网 ...
- 通过NAT转发实现私网对外发布信息
我们可以在防火墙的外部网卡上绑定多个合法IP地址,然后通过ip映射使发给其中某一个IP地址的包转发至内部某一用户的WWW服务器上,然后再将该内部WWW服务器响应包伪装成该合法IP发出的包. 具体的IP ...
- 按键精灵如何调用Excel及按键精灵写入Excel数据的方法教程---入门自动操作表格
首先来建立一个新的Excel文档,在桌面上点击右键,选择[新建]-[Excel工作表],命名为[新手学员]. 现在这个新Excel文档是空白的,我们接下来会通过按键精灵的脚本来打开并写入一些数据.打开 ...
- 国内各大安卓(Android)市场的上传方式、认领、通过审核有哪些不同,有什么值得注意的地方?
6 个回答 赞同89反对,不会显示你的姓名 唐元鹏,扯淡爱好者 Jc droid.李明亮.知乎用户 等人赞同 作为一个android菜鸟开发者,代码水平不咋样,却练就了一身上传app的本领,大体说一下 ...
- Xcode不太常见又实用的小技巧
备份, 原文: http://rocry.com/2012/12/17/xcode-tips/ 让代码中的TODO和FIXME变成Warning 选中某个Target > Build Phase ...
- mac osx voice over的使用
mac下的filezilla是一个很奇葩的应用,奇葩在哪?有一次我不知道怎么操作的,把filezilla搬到到了窗体顶部,结果被mac的菜单栏挡住了标题栏,然后再也无法移动窗体了,以下是我为了移动它做 ...