六、协议(Protocol)的原理

2018-06-05  本文已影响0人  LNG61

协议(Protocol)的定义

协议主要是用来规范一些接口的,使遵循该协议的对象都能遵循某些接口。
Protocol在runtime中定义如下:

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;
  uint32_t flags;
  const char **_txtendedMethodTypes;
  const char *_demangledname;
  property_list_t *_classProperties; // 类属性
}

协议中主要存储有一系列方法,包括@required@optional的,还有属性property。协议与Method初始化过程类似,都是在编译期便确定下来了。

协议(Protocol)的生成

首先我们先定义一个协议,并让一个类遵循该协议。

@protocol TestProtocol<NSObject>
@optional
- (void)testProtocolMethod;
@property(nonatomic) NSString *testStr;
@end

@interface TestProtocolClass : NSObject<TestProtocol>
@end

接下来我们用clang命令重写该文件。

1.遵循的协议
static struct /*_protocol_list_t*/ {
    long protocol_count;  // Note, this is 32/64 bit
    struct _protocol_t *super_protocols[1];
} _OBJC_PROTOCOL_REFS_TestProtocol __attribute__ ((used, section ("__DATA,__objc_const"))) = {
    1,
    &_OBJC_PROTOCOL_NSObject
};

_OBJC_PROTOCOL_NSObject其实就是协议NSObject

2.方法列表
static struct /*_method_list_t*/ {
    unsigned int entsize;  // sizeof(struct _objc_method)
    unsigned int method_count;
    struct _objc_method method_list[3];
} _OBJC_PROTOCOL_OPT_INSTANCE_METHODS_TestProtocol __attribute__ ((used, section ("__DATA,__objc_const"))) = {
    sizeof(_objc_method),
    3,
    {{(struct objc_selector *)"testProtocolMethod", "v16@0:8", 0},
    {(struct objc_selector *)"testStr", "@16@0:8", 0},
    {(struct objc_selector *)"setTestStr:", "v24@0:8@16", 0}}
}; 

协议TestProtocol共有三个方法,其中包含属性testStrsettergetter

3.属性
static struct /*_prop_list_t*/ {
    unsigned int entsize;  // sizeof(struct _prop_t)
    unsigned int count_of_properties;
    struct _prop_t prop_list[1];
} _OBJC_PROTOCOL_PROPERTIES_TestProtocol __attribute__ ((used, section ("__DATA,__objc_const"))) = {
    sizeof(_prop_t),
    1,
    {{"testStr","T@\"NSString\",N"}}
};
4. 协议的初始化
struct _protocol_t _OBJC_PROTOCOL_TestProtocol __attribute__ ((used)) = {
    0,
    "TestProtocol",
    (const struct _protocol_list_t *)&_OBJC_PROTOCOL_REFS_TestProtocol,
    0,
    0,
    (const struct method_list_t *)&_OBJC_PROTOCOL_OPT_INSTANCE_METHODS_TestProtocol,
    0,
    (const struct _prop_list_t *)&_OBJC_PROTOCOL_PROPERTIES_TestProtocol,
    sizeof(_protocol_t),
    0,
    (const char **)&_OBJC_PROTOCOL_METHOD_TYPES_TestProtocol
};
struct _protocol_t *_OBJC_LABEL_PROTOCOL_$_TestProtocol = &_OBJC_PROTOCOL_TestProtocol; 

最终将该协议遵循的协议、实现的方法和属性初始化为结构体protocol_t

协议中的属性与类中的属性

协议和类一样,也可以声明属性@property,不同的是,协议中的属性property=setter+getter,没有类中的变量ivar,协议中使用属性的目的就是希望遵守该协议的对象能够实现该属性。

小结:

  1. 协议主要是用来规范一些接口的,使遵循该协议的对象都能遵循某些接口。
  2. 协议和方法类似,也是在编译期便确定下来的。
  3. 协议中也能声明属性,但只会生成settergetter
上一篇 下一篇

猜你喜欢

热点阅读