iOS:通过runtime为category添加属性

2018-04-10  本文已影响24人  Waynee

本人虽然在项目中没有遇见需要给一个类的分类添加属性的情况,但在面试的过程中却被问到过。所以下面给出自己的拙见,若有不足,还请读者给出自己不同的意见。

首先:当给一个类的category添加一个属性:name。此时系统不会给此属性添加setter和getter方法,所以当在外界调用的时候会因为找不到该setter方法而crash([Person setName:]: unrecognized selector sent to instance);此时我们只需要在.m文件中实现对应的两种方法即可,因为此时无法直接用_name 接受外界传来值。所以选择了用runtime建立关联的方式。

先导入头文件<objc/runtime.h>

objc_setAssociatedObject(id_Nonnullobject,constvoid*_Nonnullkey, id_Nullablevalue, objc_AssociationPolicy policy),这个方法有四个参数,依次为:1:源对象。 2:关联时的用来标记是哪一个属性的key,此处用的是静态变量key的内存地址,也可保证唯一性。3:关联的对象(一般也是需要用到的值)。4:关联方式。

第四个关联参数一共四个枚举值,个人理解为

enum{ OBJC_ASSOCIATION_ASSIGN =0,// 看成修饰词(atomic, assign)

OBJC_ASSOCIATION_RETAIN_NONATOMIC =1,//(nonatomic, strong)

OBJC_ASSOCIATION_COPY_NONATOMIC =3,//(nonatomic, copy)

OBJC_ASSOCIATION_RETAIN =01401,//(atomic, strong)

OBJC_ASSOCIATION_COPY =01403//(atomic, copy)

}

objc_getAssociatedObject(id_Nonnullobject,constvoid*_Nonnullkey)此方法返回的其实就是上面objc_setAssociatedObject方法的第三个参数。参数对应上面的:1:源对象。 2:关联时的用来标记是哪一个属性的key。跟objc_setAssociatedObject中的值保持一致。

示例代码如下:

*********************Person+Extension.h**************************

#import "Person.h"

@interfacePerson (Extension)

@property (nonatomic, copy) NSString *name;

@end

*********************Person+Extension.m**************************

#import "Person+Extension.h"

@interface Person ()

@property (nonatomic, copy) NSString *personId;

@end

staticvoid*key = &key; // 也可以用这种方式 :staticNSString*Key =@"xxxKey";

@implementationPerson (Extension)

- (void)setName:(NSString*)name{

    objc_setAssociatedObject(self,

 key,

 name,

OBJC_ASSOCIATION_COPY_NONATOMIC);

}

- (NSString*)name{

    return objc_getAssociatedObject(self, key);

}

@end

***********************************

- (void)viewDidLoad {

    [super viewDidLoad];

    person.name=@"xxx";

    NSLog(@"%@", person.name);

}

/////// 打印结果:xxx ///////

上一篇下一篇

猜你喜欢

热点阅读