1.获取成员变量列表
1.1相关函数
Ivar可以看出也是一个变量类型
typedef struct objc_ivar *Ivar;
//获取成员变量列表
Ivar *class_copyIvarList(Class cls, unsigned int * outCount)
//获取成员变量类型编码
const char *ivar_getTypeEncoding(Ivar v)
//获取成员变量名称
const char *ivar_getName(Ivar v)
1.2实例代码
#import "ViewController.h"
#import <objc/runtime.h>
@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_copyIvarList];
}
- (void)class_copyIvarList{
uint count;
Ivar *ivars = class_copyIvarList([self class], &count);
for (unsigned int i = 0; i < count; i ++) {
Ivar ivar = ivars[i];
//获取成员变量名称
NSString* name = @(ivar_getName(ivar));
//获取成员变量数据类型
NSString * type = @(ivar_getTypeEncoding(ivar));
NSLog(@"类型为 %@ 的 %@ ",type, name);
}
free(ivars);
}
1.3打印数据
2018-05-26 10:02:36.597199+0700 runTimer[6417:1017717] 类型为 @"NSString" 的 _name
2018-05-26 10:02:36.597586+0700 runTimer[6417:1017717] 类型为 @"NSString" 的 _age
2018-05-26 10:02:36.597852+0700 runTimer[6417:1017717] 类型为 @"NSString" 的 _address
1.4查漏补缺
//通过变量名称获取类中的实例成员变量
Ivar class_getInstanceVariable(Class cls, const char * name)
实例代码及打印数据:
#import "ViewController.h"
#import <objc/runtime.h>
@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_getInstanceVariable];
}
- (void)class_getInstanceVariable{
//注意成员变量必须“_名称”
Ivar name_Ivar = class_getInstanceVariable([self class], "_name");
NSString * name_type = @(ivar_getTypeEncoding(name_Ivar));
NSString *name_str = @(ivar_getName(name_Ivar));
NSLog(@"name_type:%@",name_type);
NSLog(@"name_str:%@",name_str);
}
打印数据:
2018-05-26 10:41:17.384676+0700 runTimer[7091:1043835] name_type:@"NSString"
2018-05-26 10:41:17.384831+0700 runTimer[7091:1043835] name_str:_name
2.添加成员变量
2.1相关函数
//为元类添加成员变量
BOOL class_addIvar(Class cls, const char * name, size_t size,
uint8_t alignment, const char * types)
//添加类 superclass 类是父类 name 类的名字 size_t 类占的空间
Class objc_allocateClassPair(Class superclass, const char * name,size_t extraBytes)
//注册类
void objc_registerClassPair(Class cls)
//销毁类
void objc_disposeClassPair(Class _Nonnull cls)
2.2实例代码
- People.h
#import <Foundation/Foundation.h>
@interface People : NSObject
@end
- People.m
#import "People.h"
@implementation People
@end
3.实例调用:
#import "ViewController.h"
#import <objc/runtime.h>
#import "People.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self class_addIvar];
}
- (void)class_addIvar{
Class P_Class = objc_allocateClassPair([NSObject class], "_People", 0);
BOOL isOk = NO;
isOk = class_addIvar(P_Class,"myVar", sizeof(id), log2(sizeof(id)), "@");
isOk == YES ? nil : NSLog(@"failed on class_addIvar");
objc_registerClassPair(P_Class);
id myobj = [[P_Class alloc] init];
[myobj setValue:@"test" forKey:@"myVar"];
NSLog(@"myVar: %@", [myobj valueForKey:@"myVar"]);
myobj = nil;//当_People类或者它的子类的实例还存在,则不能调用objc_disposeClassPair这个方法;因此这里要先销毁实例对象后才能销毁类;
objc_disposeClassPair(P_Class);
}
打印数据:
2018-05-27 10:19:51.251273+0700 runTimer[14245:1323729] myVar: test
总结:
关于这个方法,说真的让我产生了一些疑惑,至今也没有得到答案,也希望看到这篇文章对runtime有一定理解朋友可以给予一定的解释,
- 疑问一:objc_allocateClassPair 在刚开始我创建获取元类时我得到总是nil,在网上查了很多资料但是我没有得到答案,后来是因为自己是性的在累名前加“_” 竟然成功的获取了,我没有明白原因。
- 疑问二:关于元类说实话我之前也是简单的知道,个人理解是关于类描述的一个类,但是我始终不能明白在元类中添加成员变量,这样做会苹果官方有什么样的深意。
3 object_setIvar object_getIvar
3.1相关函数
//相当于set方法
void object_setIvar(id obj, Ivar ivar, id value)
//相当于get方法
id object_getIvar(id obj, Ivar ivar)
3.2实例代码
1.People.h
#import <Foundation/Foundation.h>
@interface People : NSObject
@property (nonatomic,strong)NSString *phone;
@end
- People.m
#import "People.h"
@implementation People
@end
3.实例代码调用:
#import "ViewController.h"
#import <objc/runtime.h>
#import <objc/message.h>
#import "People.h"
@interface ViewController ()
@property (nonatomic,strong)People *p;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
Ivar ivar = class_getInstanceVariable([People class], "_phone");
People *p = [[People alloc] init];
p.phone = @"1322432423";
id name1 = object_getIvar(p, ivar);
NSLog(@"name1:%@",name1);
object_setIvar(p, ivar, @"1322432423");
id name2 = object_getIvar(p, ivar);
NSLog(@"name2:%@",name2);
}
打印数据:
2018-05-27 11:05:04.551576+0700 runTimer[14991:1353337] name1:1322432423
2018-05-27 11:05:04.551717+0700 runTimer[14991:1353337] name2:1322432423
总结:
看到这里的时候我想大家已经很明白了 这两个方法 基本上等同于set get方法。
4.未做解析方法:
ivar_getOffset
class_setWeakIvarLayout
object_setIvarWithStrongDefault
class_getWeakIvarLayout
class_getIvarLayout
好了 就那么多了 还有一些方法没有讲,太懒了,就不一一解析了。
下一章,关于runtime 关于method的解析
网友评论