版权声明:原创作品,谢绝转载!否则将追究法律责任。

在现实生活中,当处理某一情况的时候人们往往遵循严格的程序。执法人员他们在打官司的收集证据和询问的时候一定要遵守协议。

在面向对象的语言中,最重要的是一个对象需要定义一些行为在某种情况下。例如:一个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官方文档 协议的更多相关文章

  1. gRPC官方文档(通讯协议)

    文章来自gRPC 官方文档中文版 HTTP2 协议上的 gRPC 本文档作为 gRPC 在 HTTP2 草案17框架上的实现的详细描述,假设你已经熟悉 HTTP2 的规范.产品规则采用的是ABNF 语 ...

  2. Spring 4 官方文档学习 Spring与Java EE技术的集成

    本部分覆盖了以下内容: Chapter 28, Remoting and web services using Spring -- 使用Spring进行远程和web服务 Chapter 29, Ent ...

  3. Spring 4 官方文档学习(十四)WebSocket支持

    个人提示:如果需要用到页面推送,高频且要低延迟,WebSocket无疑是最佳选择.否则还是轮询和long polling吧. 做了一个小demo放在码云上,有兴趣的可以看一下,简单易懂:websock ...

  4. OC-苹果官方文档

    苹果官方文档 help>documentation>左边iOS>language>objective>the objective-c programming langua ...

  5. clang format 官方文档自定义参数介绍(中英文)

    官方文档:http://clang.llvm.org/docs/ClangFormatStyleOptions.html 中文 在代码中配置样式 当使用 clang::format::reformat ...

  6. 自己翻译 delegation 官方文档

    什么是代理,知道怎么用,见过N次.会用代理传值,还不够.代理到底是用来干嘛的嘛?还是看看官方文档吧,自己翻译出来看看是不是通顺 代理: 代理是一个简单高效的模式,尤其是一个类在编程的过程中代表或者需要 ...

  7. spring官方文档中文版

    转 http://blog.csdn.net/tangtong1/article/details/51326887 spring官方文档:http://docs.spring.io/spring/do ...

  8. ios学习笔记第四天之官方文档总结

    start developing ios app today. 官方文档的体系结构为: 各层的主要框架图: objectice-c是动态语言 Objective-C 为 ANSI C 添加了下述语法和 ...

  9. Spring Cloud官方文档中文版-服务发现:Eureka服务端

    官方文档地址为:http://cloud.spring.io/spring-cloud-static/Dalston.SR3/#spring-cloud-eureka-server 文中例子我做了一些 ...

随机推荐

  1. iOS项目的目录结构(Cocoa China)

    目录结构 AppDelegate Models Macro General Helpers Vendors Sections Resources   一个合理的目录结构首先应该是清晰的,让人一眼看上去 ...

  2. unity---Courtine 协程

    尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com 记得去年6月份刚开始实习的时候,当时要我写网络层的结构,用到了协程,当时有点懵,完全不知道Unity协程的执行机制是 ...

  3. nodejs基础 -- 多进程

    Node.js 多进程 我们都知道 Node.js 是以单线程的模式运行的,但它使用的是事件驱动来处理并发,这样有助于我们在多核 cpu 的系统上创建多个子进程,从而提高性能. 每个子进程总是带有三个 ...

  4. 使用vi时提示 write error in swap file

    今天使用vi 命令时,提示write error in swap file 查了下原因,磁盘空间不够 df -h 使用 rm -rf 文件名 ,删除不用的 使用 echo "" & ...

  5. pycharm pro版本激活

    这几天行激活pycharm pro版会遇到问题,license server的网址都不可用了.包括各个网站的百度云的破解资源链接都被和谐了,发现最近jetbrains对盗版管得严. 首次安装在注册界面 ...

  6. struts2 第一次使用 404 页面引发的一系列问题

    环境:ubuntu  . eclipse.struts-2.3.24 问题描写叙述: 1.  struts2 訪问出现404 2.  严重: Exception starting filter Str ...

  7. JAVAWEB开发之Session的追踪创建和销毁、JSP具体解释(指令,标签,内置对象,动作即转发和包括)、JavaBean及内省技术以及EL表达式获取内容的使用

    Session的追踪技术 已知Session是利用cookie机制的server端技术.当client第一次訪问资源时 假设调用request.getSession() 就会在server端创建一个由 ...

  8. Dubbo -- 系统学习 笔记 -- 示例 -- 只订阅

    Dubbo -- 系统学习 笔记 -- 目录 示例 想完整的运行起来,请参见:快速启动,这里只列出各种场景的配置方式 只订阅 问题 为方便开发测试,经常会在线下共用一个所有服务可用的注册中心,这时,如 ...

  9. 5 -- Hibernate的基本用法 --4 9 其他常用的配置属性

    Hibernate其他常用的配置属性: ⊙ hibernate.show_sql : 是否在控制台输出Hibernate持久化操作底层所使用的SQL语句.只能为true和false两个值. ⊙ hib ...

  10. 5 -- Hibernate的基本用法 --1 2 基本映射方式

    ORM工具提供了持久化类和数据表之间的映射关系.实际上,所有的ORM工具大致上都遵循相同的映射思路,ORM基本映射有如下几条映射关系: ⊙ 数据表映射类 : 持久化类被映射到一个数据表.程序使用这个持 ...