runtime官方文章学习大纲
1. 读取类的Property属性
1.1相关函数
typedef struct objc_property *objc_property_t;
typedef struct {
const char *name;
const char *value;
} objc_property_attribute_t;
// 获取指定的属性
objc_property_t class_getProperty ( Class cls, const char *name );
// 获取属性列表
objc_property_t * class_copyPropertyList ( Class cls, unsigned int *outCount );
//获取属性名称
const char * property_getName(objc_property_t _Nonnull property)
//获取属性特性
const char *property_getAttributes(objc_property_t _Nonnull property)
//获取属性特性列表
objc_property_attribute_t *property_copyAttributeList(objc_property_t property,unsigned int * outCount)
//获取根据特定键获取想得到的属性特性
char *property_copyAttributeValue(objc_property_t property, const char * attributeName)
1.2.案例代码:
#import "ViewController.h"
#import
@interface ViewController ()
@property (nonatomic,strong)NSString *name;
@property (atomic,strong)NSString *age;
@property (nonatomic,assign)BOOL isMan;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self class_copyPropertyList];
}
- (void)class_copyPropertyList{
//得到当前class的所有属性
unsigned int count;
objc_property_t *properties = class_copyPropertyList([self class], &count);
for (int i = 0; i
1.3.打印数据:
2018-05-24 14:48:35.663763+0700 runtime [28461:2078183]
property_name:name
property_attr:T@"NSString",&,N,V_name
propertyType:@"NSString"
property_Value:_name
2018-05-24 14:48:35.663940+0700 runtime [28461:2078183] attribute name: T, value: @"NSString"
2018-05-24 14:48:35.664034+0700 runtime [28461:2078183] attribute name: &, value:
2018-05-24 14:48:35.664124+0700 runtime [28461:2078183] attribute name: N, value:
2018-05-24 14:48:35.664259+0700 runtime [28461:2078183] attribute name: V, value: _name
2018-05-24 14:48:35.664399+0700 runtime [28461:2078183]
property_name:age
property_attr:T@"NSString",&,V_age
propertyType:@"NSString"
property_Value:_age
2018-05-24 14:48:35.664516+0700 runtime [28461:2078183] attribute name: T, value: @"NSString"
2018-05-24 14:48:35.664600+0700 runtime [28461:2078183] attribute name: &, value:
2018-05-24 14:48:35.664677+0700 runtime [28461:2078183] attribute name: V, value: _age
2018-05-24 14:48:35.664756+0700 runtime [28461:2078183]
property_name:isMan
property_attr:TB,N,V_isMan
propertyType:B
property_Value:_isMan
2018-05-24 14:48:35.664850+0700 runtime [28461:2078183] attribute name: T, value: B
2018-05-24 14:48:35.664934+0700 runtime [28461:2078183] attribute name: N, value:
2018-05-24 14:48:35.665079+0700 runtime [28461:2078183] attribute name: V, value: _isMan
1.4.分析:
- property_getName:通过property_getName获取属性对象名称
- property_getAttributes:通过property_getAttributes获取 属性的特性字符串 以 T@encode(type) 开头, 以 V实例变量名称 结尾,中间以特性编码填充.
- property_copyAttributeList:为属性对象列表 等同于property_getAttributes 区别在于一个返回数组一个返回字符串。
- objc_property_attribute_t:为property_copyAttributeList包含的数组对象
- property_copyAttributeValue:获取对应的属性特性描述,可以理解为在property_copyAttributeList中的值都可以单独获取到。
1.5.特性编码解析
1.property_attribute为T@”NSString”,&,N,V_exprice时:
T 是固定的,放在第一个
@”NSString” 代表这个property是一个字符串对象
& 代表强引用,其中与之并列的是:’C’代表Copy,’&’代表强引用,’W’表示weak,assign为空,默认为assign。
N 区分的nonatomic和atomic,默认为atomic,atomic为空,’N’代表是nonatomic
V_exprice V代表变量,后面紧跟着的是成员变量名,代表这个property的成员变量名为_exprice。
2.property_attribute为T@”NSNumber”,R,N,V_yearsOld时:
T 是固定的,放在第一个
@”NSNumber” 代表这个property是一个NSNumber对象
R 代表readOnly属性,readwrite时为空
N 区分的nonatomic和atomic,默认为atomic,atomic为空,’N’代表是nonatomic
V_yearsOld V代表变量,后面紧跟着的是成员变量名,代表这个property的成员变量名为_yearsOld。
3.对应的编码值
//下面对应的编码值可以在官方文档里面找到
//编码值 含意
//c 代表char类型
//i 代表int类型
//s 代表short类型
//l 代表long类型,在64位处理器上也是按照32位处理
//q 代表long long类型
//C 代表unsigned char类型
//I 代表unsigned int类型
//S 代表unsigned short类型
//L 代表unsigned long类型
//Q 代表unsigned long long类型
//f 代表float类型
//d 代表double类型
//B 代表C++中的bool或者C99中的_Bool
//v 代表void类型
//* 代表char *类型
//@ 代表对象类型
//# 代表类对象 (Class)
//: 代表方法selector (SEL)
//[array type] 代表array
//{name=type…} 代表结构体
//(name=type…) 代表union
//bnum A bit field of num bits
//^type A pointer to type
//? An unknown type (among other things, this code is used for function pointers)
4.其他
G(name) getter=(name)
S(name) setter=(name)
D @dynamic
P 用于垃圾回收机制
推荐解析文章
特性编码解析大全
案例图
1.6查漏补缺
获取单个属性的信息
#import "ViewController.h"
#import
@interface ViewController ()
@property (nonatomic,strong)NSString *name;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self class_getProperty:[self class] name:"name"];
}
- (void)class_getProperty:(Class)class name:(const char *)name {
objc_property_t property = class_getProperty(class,name);
NSString *property_name = @(property_getName(property));
NSString *property_attr = @(property_getAttributes(property));
NSString *property_Value = @(property_copyAttributeValue(property, "V"));
NSString *property_Type = @(property_copyAttributeValue(property, "T"));
NSLog(@"\n property_name:%@ \n property_attr:%@,\n property_Type:%@ \n property_Value:%@",property_name,property_attr,property_Type,property_Value);
}
打印数据:
2018-05-24 16:51:58.266463+0700 runtime [29718:2161350]
property_name:name
property_attr:T@"NSString",&,N,V_name,
property_Type:@"NSString"
property_Value:_name
看代码就明白了,不解释了,很多知识由面到点,会更精彩一些。
2.替换类的Property属性
相关函数
// 替换类的属性
void class_replaceProperty ( Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount );
实例代码:
#import "ViewController.h"
#import
@interface ViewController ()
@property (nonatomic,strong)NSString *name;
@property (nonatomic,assign)NSString *age;
@property (nonatomic,strong)NSString *address;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self class_replaceProperty:[self class] class_name:"name" replace_name:"nick_name"];
//对name进行特性获取
[self class_getProperty:[self class] name:"name"];
}
- (void)class_replaceProperty:(Class)class class_name:(const char *)class_name replace_name:(const char *)replace_name{
objc_property_attribute_t type = { "T", "@\"NSString\"" };
objc_property_attribute_t ownership = { "C", "" }; // C = copy
objc_property_attribute_t backingivar = { "V", replace_name };
objc_property_attribute_t attrs[] = { type, ownership, backingivar };
class_replaceProperty(class, class_name, attrs, 3);
}
- (void)class_getProperty:(Class)class name:(const char *)name {
objc_property_t property = class_getProperty(class,name);
NSString *property_name = @(property_getName(property));
NSString *property_attr = @(property_getAttributes(property));
NSString *property_Value = @(property_copyAttributeValue(property, "V"));
NSString *property_Type = @(property_copyAttributeValue(property, "T"));
NSLog(@"\n property_name:%@ \n property_attr:%@,\n property_Type:%@ \n property_Value:%@",property_name,property_attr,property_Type,property_Value);
}
分析:
从打印数据的数据我们对比可以发,所谓替换属性并不是说直接讲声明的名称改掉,而是将属性特性值改为我们所需要的。
3.为类添加Property
相关函数
BOOL class_addProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount)
实例代码
#import "ViewController.h"
#import
@interface ViewController ()
@property (nonatomic,strong)NSString *name;
@property (nonatomic,assign)NSString *age;
@property (nonatomic,strong)NSString *address;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//新增nick_name
[self class_addProperty:[self class] add_name:"nick_name"];
//对nick_name进行特性获取
[self class_getProperty:[self class] name:"nick_name"];
}
- (void)class_addProperty:(Class)class add_name:(const char *)add_name {
objc_property_attribute_t type = { "T", "@\"NSString\"" };
objc_property_attribute_t ownership = { "&", "N" }; // C = copy
objc_property_attribute_t backingivar = { "V", "" };
objc_property_attribute_t attrs[] = { type, ownership, backingivar };
if (class_addProperty(class, add_name, attrs, 3)) {
NSLog(@"添加属性--%sadd Property success",__func__);
}else{
NSLog(@"添加属性--%sadd Property fail",__func__);
}
}
- (void)class_getProperty:(Class)class name:(const char *)name {
objc_property_t property = class_getProperty(class,name);
NSString *property_name = @(property_getName(property));
NSString *property_attr = @(property_getAttributes(property));
NSString *property_Value = @(property_copyAttributeValue(property, "V"));
NSString *property_Type = @(property_copyAttributeValue(property, "T"));
NSLog(@"\n property_name:%@ \n property_attr:%@,\n property_Type:%@ \n property_Value:%@",property_name,property_attr,property_Type,property_Value);
}
打印数据:
2018-05-26 09:29:05.939306+0700 runTimer[5930:999110] 添加属性---[ViewController class_addProperty:add_name:]add Property success
2018-05-26 09:29:05.939474+0700 runTimer[5930:999110]
property_name:nick_name
property_attr:T@"NSString",&N,V,
property_Type:@"NSString"
property_Value:
分析:
对比替换属性进行分析,会更加透彻。
runtime之Property 讲解就完毕了。不足指出还请指正。
下一章:Ivar 详解晚更~