1、分类有个特性:就是使用 @property 创建属性,只会生成 setter、getter 方法的声明,而没有生成setter、getter 方法的实现 和 _变量。
2、解决方法:在分类实现setter、getter 方法中,使用runtime 动态创建属性。但是runtime 也不会自动生成 _变量,因此如果使用对象调用 _变量 时会报错。
3、代码展示
#import "Person.h"
NS_ASSUME_NONNULL_BEGIN
// Person 类的分类
@interface Person (Add)
//使用 @property 给分类添加属性,只会生成 setter、getter 方法的声明。而不会生成 setter、getter 方法的实现 和 _变量。可以使用 runtime 关联对象 动态创建属性
@property(nonatomic, copy)NSString *name;
@end
NS_ASSUME_NONNULL_END
#import "Person+Add.h"
//引入runtime的头文件
#import <objc/runtime.h>
@implementation Person (Add)
-(void)setName:(NSString *)name {
/*
OBJC_ASSOCIATION_ASSIGN; //assign策略
OBJC_ASSOCIATION_COPY_NONATOMIC; //copy策略
OBJC_ASSOCIATION_RETAIN_NONATOMIC; // retain策略
OBJC_ASSOCIATION_RETAIN;
OBJC_ASSOCIATION_COPY;
*/
/**
objc_setAssociatedObject(id _Nonnull object, const void * _Nonnull key,
id _Nullable value, objc_AssociationPolicy policy)
1、object:保存到哪个对象中(给哪个对象的属性赋值)
2、key:属性对应的 key
3、value:设置属性值
4、policy:使用的策略,是一个枚举值,和copy,retain,assign是一样的,手机开发一般都选择NONATOMIC
*/
//动态创建属性
objc_setAssociatedObject(self, "name", name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
-(NSString *)name {
return objc_getAssociatedObject(self, "name");
}
@end
#import <Foundation/Foundation.h>
#import "Person+Add.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *p1 = [[Person alloc]init];
//通过runtime调用 p1对象 name 属性的setter 和 getter 方法来动态创建属性,但是不能 创建出 _变量
[p1 setName:@"张三"];
NSLog(@"name = %@",[p1 name]);
// p1 -> _name = @"张三"; //这样程序报错,因为在分类中使用 @property 不会生成 _变量
}
return 0;
}