苹果官方的解释:html
Delegation is a simple and powerful pattern in which one object in a program acts on behalf of, or in coordination with, another object. The delegating object keeps a reference to the other object—the delegate—and at the appropriate time sends a message to it. The message informs the delegate of an event that the delegating object is about to handle or has just handled. The delegate may respond to the message by updating the appearance or state of itself or other objects in the application, and in some cases it can return a value that affects how an impending event is handled. The main value of delegation is that it allows you to easily customize the behavior of several objects in one central object.java
其大意是:代理是一种简单而强大的模式,委托方持有代理对象的引用,并对其发送消息,代理方接收消息并处理返回结果。其主要价值在于,能实现一个对象中实现多个对象的功能,相似“多继承”。c++
代理模式是通用的设计模式,Cocoa框架中大量使用了这种模式来实现数据和UI的分离,如UITableView
、UIApplicationDelegate
等,其主要有三部分组成:git
直观的关系图以下(借楼): github
下面将重点阐述“协议”的概念及使用;objective-c
Protocol
协议相似java
中的接口或者c++
中的纯虚函数,只提供接口不提供实现,Î不一样于c++
中的纯虚函数,其不存在类继承关系,但遵循协议继承。segmentfault
@protocol FSSubDelegate <NSObject, FSDelegate>
@required
//methodList or protertyList
@optional
//methodList or protertyList
@end
复制代码
协议中存在两个修饰符@required
和@optional
,默认为@required
,修饰符指示遵循协议下的方法或者属性是否必需要实现.设计模式
协议须要继承“基协议”NSObject
(不一样于NSObject
基类),其中规定了一些全部基类都须要实现的基本方法和属性,好比isEqual:
、isKindOfClass
、respondsToSelector
等,内存管理的方法retain
、release
、autorelease
、retainCount
等,这样就定义了一个相对统一的接口和 OC
对象均可以响应的方法。OC
对象是不支持多继承的,但协议能够多继承。app
注意:协议中是能够添加属性,只是在代理模式中不多使用,但类别category是没法添加属性,除非使用关联对象。框架
协议中经常使用的继承自NSObject
基协议的方法以下:
- (BOOL)conformsToProtocol:(Protocol *)aProtocol;
- (BOOL)respondsToSelector:(SEL)aSelector;
复制代码
因为协议是“类无关”的,任何类均可以实现定义好的协议,所以能够经过conformsToProtocol:
方法来判别某个类是否实现了特定协议;即便协议中指定了@required
,代理对象也能够不遵循协议规定不实现协议必须实现的方法(只是编译警告),能够经过respondsToSelector
来判别代理对象是否实现了特定方法,避免运行期崩溃。
对于协议定义的位置,可根据使用状况来决定,若是只是使用在某个类中,可直接定义在类文件中;若多个类都是用同一个协议,可定义在统一的文件中。
以开放中常见的UITableView
为例说明,通常的使用以下:
@protocol UITableViewDelegate <NSObject, UIScrollViewDelegate>
...
@end
@protocol UITableViewDataSource <NSObject>
...
@end
@interface UITableView
@property (nonatomic, weak, nullable) id <UITableViewDelegate> delegate;
@end
@implementation UIViewController <UITableViewDelegate, UITableViewDataSource>
- (void) viewDidLoad {
self.tableView.delegate = self;
self.tableView.dataSource = self;
}
#pragma mark -- UITableViewDelegate
//须要遵循实现的协议方法
#pragma mark -- UITableViewDataSource
////须要遵循实现的协议方法
@end
复制代码
基于代理模式的关系图解释,其中协议为UITableViewDelegate
及UITableViewDataSource
分别提出了
UITableVeiwCell
的显示、编辑、选择及其内容、索引、数目等需求;委托方为UITableView
持有弱引用的代理对象delegate
,经过delegate
调用协议中的方法并传递参数;代理方UIViewController
须要实现协议中的方法来完成UITableView
中的需求,最终实现UITableView
控件的内容显示、编辑、滑动、跳转等动做。其中委托方中的代理属性须要为弱引用,避免与代理方循环引用而两个对象没法释放。
经过上述通用案例说明:委托方能够存在多个代理对象,一个代理对象也能够有多个委托方(如数据源代理对象可经过分离对象实现,而不指定为UIViewController
,以实现松耦合)。
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY;
...
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE;
} OBJC2_UNAVAILABLE;
struct objc_protocol_list {
struct objc_protocol_list * _Nullable next;
long count;
__unsafe_unretained Protocol * _Nullable list[1];
};
struct protocol_t : objc_object {
const char *mangledName;
struct protocol_list_t *protocols;
method_list_t *instanceMethods;
method_list_t *classMethods;
method_list_t *optionalInstanceMethods;
method_list_t *optionalClassMethods;
property_list_t *instanceProperties;
uint32_t size; // sizeof(protocol_t)
uint32_t flags;
// Fields below this point are not always present on disk.
const char **_extendedMethodTypes;
const char *_demangledName;
property_list_t *_classProperties;
//省略一些封装的便捷 get 方法
....
};
复制代码
观察类对象的结构可发现存在struct objc_protocol_list
类型的协议链表,而且协议结构体中存在属性信息(也说明协议中可定义属性),所以代理对象实现协议方法,即将协议方法添加至类对象中,可经过以下runtime
方法获取协议方法: 具体的类结构图信息以下图所示(借楼):
method
来避免消息转发)。
Cocoa Core Competencies -- Delegation