【靠谱程序员】【7】Protocol与Category

本文最后更新于:2021年12月22日 上午

【靠谱程序员】系列目录


问:

在@protocol 和 category 中如何使用 @property

答:

  • 1、在 protocol 中使用 property 只会生成 setter 和 getter 方法声明,我们使用属性的目的,是希望遵守我协议的对象能实现该属性

  • 2、category 使用 @property 也是只会生成 setter 和 getter 方法的声明,如果我们真的需要给 category 增加属性的实现,需要借助于运行时的两个函数:

    1
    2
    objc_setAssociatedObject
    objc_getAssociatedObject

示例代码

1
2
3
4
5
6
7
8
9
10
//Person.h
// 本类头文件及实现文件
#import <Foundation/Foundation.h>

@interface Person : NSObject

// 声明一个属性
@property (nonatomic, copy) NSString *name;

@end
1
2
3
4
5
6
7
//Person.m
#import "Person.h"

@implementation Person

@end

Person+Extension.h

1
2
3
4
5
6
7
8
9
10
// 分类头文件及实现文件

#import "Person.h"

@interface Person (Extension)

// 分类中声明属性,只会生成setter和getter方法的声明,不会生成带“_”的成员变量和setter和getter方法的实现
@property (nonatomic, assign) NSInteger age;

@end

Person+Extension.m

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#import "Person+Extension.h"

// 使用运行时,需要导入头文件
#import <objc/runtime.h>

@implementation Person (Extension)

- (void)setAge:(NSInteger)age{
// 使用运行时关联对象,person对象(self)强引用age对象,并且设置标记为"age"(可以根据该标记来获取引用的对象age,标记可以为任意字符,只要setter和getter中的标记一致就可以)
// 参数1:源对象
// 参数2:关联时用来标记属性的key(因为可能要添加很多属性),很多人习惯使用char *类型的key,如static char *key = "age",那这里需要传入&key,但是使用iOS的NSString类型的字符常量也是可以的,目测估计这里需要内存地址一致,有兴趣可以试试给objc_setAssociatedObject的key对象 new一个NSString然后再objc_getAssociatedObject的key new一个新的字面量相同的新的key对象
// 参数3:关联的对象
// 参数4:关联策略
objc_setAssociatedObject(self@"age", @(age), OBJC_ASSOCIATION_RETAIN);
}

- (NSInteger)age{
// 根据“age”标识取person对象(self)强引用的age对象
// 参数1:源对象
// 参数2:关联时用来标记属性的key(因为可能要添加很多属性)
return [objc_getAssociatedObject(self@"age") integerValue];
}

@end

objc_AssociationPolicy的定义:

1
2
3
4
5
6
7
enum {
OBJC_ASSOCIATION_ASSIGN = 0, //assign
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, //retain
OBJC_ASSOCIATION_COPY_NONATOMIC = 3, //copy
OBJC_ASSOCIATION_RETAIN = 01401,
OBJC_ASSOCIATION_COPY = 01403
};

联系方式

邮箱: xiebangyao_1994@163.com

相关账号: