Protocol概述

来源:互联网 发布:芜湖神淘宝店 编辑:程序博客网 时间:2024/05/20 20:47

Protocol概述

*OO的世界,可能会希望某对象在特定条件下会有特定的行为。*

As an example, a table view expects to be able to communicate with a data source object in order to find out what it is required to display. This means that the data source must respond to a specific set of messages that the table view might send.

* Table view对象会和Data source对象进行交互,从而获得需要显示的数据。也就是说,Data source对象必须对Table view发送的一系列特定消息进行正确响应。 *

The data source could be an instance of any class, such as a view controller (a subclass of NSViewController on OS X or UIViewController on iOS) or a dedicated data source class that perhaps just inherits from NSObject. In order for the table view to know whether an object is suitable as a data source, it’s important to be able to declare that the object implements the necessary methods.

但是有一个问题:这个数据源对象可以是任意类对象(只要有数据),比如view controller,或者一个指定的数据源类。为了让table view知道一个对象是否适合作为数据源,就必须为数据源对象添加一些必要的对象方法。

Objective-C allows you to define protocols, which declare the methods expected to be used for a particular situation.

OC中允许定义protocol来声明一些用于特定环境下方法。

A class interface declares the methods and properties associated with that class. A protocol, by contrast, is used to declare methods and properties that are independent of any specific class.

类的接口中声明的是和本类相关联的方法和属性。与之相对,Protocol里面声明的是一些独立的属性和方法,不和任何特定类关联。

基本语法

@protocol ProtocolName//list of methods and properties@end

在protocol中可以有类方法也可以有对象方法声明,也可以包含属性声明。

比如你有一个显示饼状图的应用界面,界面内的饼状图内容需要由其他对象提供(保证饼状图的可重用性,从不同的源获得不同信息,这样就不用再做一个不同的饼状图来捆绑不同的数据源),比如它需要从一个数据源对象获取信息。

The minimum information needed by the pie chart view includes the number of segments, the relative size of each segment, and the title of each segment. The pie chart’s data source protocol, therefore, might look like this:

这个饼状图中需要的基本信息有:分块数目、块大小、块内容。

所以这个饼状图的protocol可以像下面这样写:

@protocol XYZPieChartViewDataSource
//对象方法:分块数目
- (NSUInteger)numberOfSegments;
//对象方法:分块大小
- (CGFloat)sizeOfSegmentAtIndex:(NSUInteger)segmentIndex;
//对象方法:分块内容
- (NSString *)titleForSegmentAtIndex:(NSUInteger)segmentIndex;
@end

The pie chart view class interface would need a property to keep track of the data source object. This object could be of any class, so the basic property type will be id. The only thing that is known about the object is that it conforms to the relevant protocol.

这个饼状图类中需要包含一个追踪数据源对象的属性。这个属性可以追踪任意类型的数据源,所以它的类型是id。现在对任意数据源对象的了解仅仅是:它们会遵从相关的protocol。

用于追踪数据源对象的属性如下所示:

@interface XYZPieChartView : UIView//弱引用,协议名XYZPieChartViewDataSource,dataSource@property (weak) id <XYZPieChartViewDataSource> dataSource;...@end

Objective-C uses angle brackets to indicate conformance to a protocol. This example declares a weak property for a generic object pointer that conforms to the XYZPieChartViewDataSource protocol.

这个类中dataSource属性中间用尖括号括起来的XYZPieChartViewDataSource指定的是protocol的名称,表示这个属性对象是遵从这个protocol的。

Note: Delegate and data source properties are usually marked as weak for the object graph management reasons described earlier, in Avoid Strong Reference Cycles.

委托和数据源属性通常都被标记为weak(弱引用),这是基于对象关系管理的考虑,避免强引用环的出现。

Protocol里面可以存在可选方法(Optional Method)

通常情况下protocol里面声明的方法都是必须的,就是说任何使用这个protocol的类中都必须把这些方法全部实现。但也可以使用@optional来声明可选的方法,这样的方法在类中是选择性实现的。
- protocol内可选方法语法

@protocol XYZPieChartViewDataSource- (NSUInteger)numberOfSegments;- (CGFloat)sizeOfSegmentAtIndex:(NSUInteger)segmentIndex;//以下为可选方法:@optional- (NSString *)titleForSegmentAtIndex:(NSUInteger)segmentIndex;@end

In this case, only the titleForSegmentAtIndex: method is marked optional. The previous methods have no directive, so are assumed to be required.

上面的例子中,只有titleForSegmentAtIndex是可选的方法。之前的没有@optional的方法都被认为是必须的方法。

The @optional directive applies to any methods that follow it, either until the end of the protocol definition, or until another directive is encountered, such as @required.

@optional之后的方法都是可选的,直到遇到另外的控制符,比如@required。

//protocol名称@protocol XYZPieChartViewDataSource//------------------required----------------------- (NSUInteger)numberOfSegments;- (CGFloat)sizeOfSegmentAtIndex:(NSUInteger)segmentIndex;//------------------optional----------------------@optional- (NSString *)titleForSegmentAtIndex:(NSUInteger)segmentIndex;- (BOOL)shouldExplodeSegmentAtIndex:(NSUInteger)segmentIndex;//------------------required----------------------@required- (UIColor *)colorForSegmentAtIndex:(NSUInteger)segmentIndex;@end

在使用可选方法的时候需要注意:
你要调用它的话必须保证它在被调对象类中已经实现了。

Remember: Local object variables are automatically initialized to nil.

protocol的继承

it’s best practice to define your protocols to conform to the NSObject protocol (some of the NSObject behavior is split from its class interface into a separate protocol; the NSObject class adopts the NSObject protocol).

可以定义一个遵从NSObject协议的协议(NSObject类的一些行为被单独分割到了一个协议中,NSObject类遵守NSObject协议)。

  • 定义一个继承另外一个协议的协议的语法:
//MyProtocol协议遵从NSObject协议@protocol MyProtocol <NSObject>...@end

By indicating that your own protocol conforms to the NSObject protocol, you’re indicating that any object that adopts the custom protocol will also provide implementations for each of the NSObject protocol methods.

比如上面的代码,指定MyProtocol遵守NSObject协议,即任何遵从MyProtocol的对象都需要提供NSObject协议内方法的实现。

Conforming to Protocols(协议的实现)

@interface MyClass : NSObject <MyProtocol>...@end

代码中MyClass类继承自NSObject类,并且遵从MyProtocol协议。这样的话MyClass类对象不仅能够对自己的方法做出相应,也会对MyProtocol声明的required方法作出响应。

Note: The compiler does not automatically synthesize properties declared in adopted protocols.

声明一个接受多个协议的类

//多个协议用逗号分隔@interface MyClass : NSObject <MyProtocol, AnotherProtocol, YetAnotherProtocol>...@end

**Tip: If you find yourself adopting a large number of protocols in a class, it may be a sign that you need to refactor an overly-complex class by splitting the necessary behavior across multiple smaller classes, each with clearly-defined responsibilities.
One relatively common pitfall for new OS X and iOS developers is to use a single application delegate class to contain the majority of an application’s functionality (managing underlying data structures, serving the data to multiple user interface elements, as well as responding to gestures and other user interaction). As complexity increases, the class becomes more difficult to maintain.**

提示:当你发现某个类同时接受了大量的协议,这个类已经变得极度复杂了。你需要将这个类重构分隔为多个具有简单功能,接口清晰的小类。OSX和iOS新手开发者经常使用一个代理类实现应用程序的绝大部分功能。但是当这个类变得越来越复杂的时候,这个类也变得越来越难以维护。

Cocoa and Cocoa Touch Define a Large Number of Protocols

Protocols Are Used for Anonymity

0 0
原创粉丝点击