iOS底层原理runtime 方法列表 以及常用api调用
objc_系列函数关注于宏观使用,如类与协议的空间分配,注册,注销等操作
class_系列函数关注于类的内部,如实例变量,属性,方法,协议等相关问题
objcet_系列函数关注于对象的角度,如实例变量
method_系列函数关注于方法内部,如果方法的参数及返回值类型和方法的实现
property_系类函数关注与属性*内部,如属性的特性等
protocol_系类函数关注与协议相关
ivar_xxx函数关注与实例变量的东西
sel_xxx主要讨论关于方法编号相关的东西
imp_xxx主要讨论关于方法实现相关的
下面我们来玩一下这些常用的api
//交换方法
Method m1 = class_getInstanceMethod(self, @selector(viewWillAppear:));
Method m2 = class_getInstanceMethod(self, @selector(tz_viewWillAppear:));
method_exchangeImplementations(m1, m2);
// 关联属性
- (void)setViewColor:(NSString *)viewColor{
objc_setAssociatedObject(self, &associatedObjectKey, @"addProperty", OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSString *)viewColor{
return objc_getAssociatedObject(self, &associatedObjectKey);
}
/// 创建一类对
Class TZCat = objc_allocateClassPair([NSObject class], "TZCat", 0);
/// 添加实例变量
// const char* types= "v@:"
NSString* name = @"name";
class_addIvar(TZCat, name.UTF8String, sizeof(id), log2(sizeof(id)), @encode(id));
// 添加方法
class_addMethod(TZCat, @selector(hunting), (IMP)hunting, "v@:");
/// 注册类
objc_registerClassPair(TZCat);
// 创建实例对象
id cat = [[TZCat alloc] init];
[cat setValue:@"Tom" forKey:@"name"];
NSLog(@"name = %@", [cat valueForKey:name]);
/// 方法调用
[cat performSelector:@selector(hunting)];
// 获取成员变量列表
unsigned int count = 0;
Ivar* ivars = class_copyIvarList([self class], &count);
for (int i = 0; i < count; i++) {
Ivar var = ivars[i];
const char* name = ivar_getName(var);
NSString* key = [NSString stringWithUTF8String:name];
id value = [self valueForKey:key];
[aCoder encodeObject:value forKey:key];
}
free(ivars);
消息转发机制
/*
* 第一步 实例方法专用 方法解析
**/
+ (BOOL)resolveInstanceMethod:(SEL)sel{
NSLog(@"%@",NSStringFromSelector(sel));
if(sel == @selector(DoThings:Num:)){
class_addMethod([self class], sel, (IMP)MyMethodIMP, "v@:");
return YES;
}
return [super resolveInstanceMethod:sel];
}
/*
* 第二步 如果第一步未处理,那么让别的对象去处理这个方法
**/
-(id)forwardingTargetForSelector:(SEL)aSelector{
if([NSStringFromSelector(aSelector) isEqualToString:@"DoThings:Num:"]){
return [[Tools alloc]init];
}
return [super forwardingTargetForSelector:aSelector];
}
/*
* 第三步 如果前两步未处理,这是最后处理的机会将目标函数以其他形式执行
**/
-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
NSString *SelStr = NSStringFromSelector(aSelector);
if([SelStr isEqualToString:@"DoThings:Num:"]){
[NSMethodSignature signatureWithObjCTypes:"v@:"];
}
return [super methodSignatureForSelector:aSelector];
}
-(void)forwardInvocation:(NSInvocation *)anInvocation{
//改变消息接受者对象
[anInvocation invokeWithTarget:[[Tools alloc]init]];
//改变消息的SEL
anInvocation.selector = @selector(flyGame);
[anInvocation invokeWithTarget:self];
}
- (void)flyGame{
NSLog(@"我要飞翔追逐梦想!");
}
/*
* 作为找不到函数实现的最后一步,NSObject实现这个函数只有一个功能,就是抛出异常。
* 虽然理论上可以重载这个函数实现保证不抛出异常(不调用super实现),但是苹果文档着重提出“一定不能让这个函数就这么结束掉,必须抛出异常”。
*
***/
- (void)doesNotRecognizeSelector:(SEL)aSelector{
}
消息机制
objc_msgSend("对象","SEL","参数"...)
objc_msgSend( id self, SEL op, ... )
runtime 源码地址:https://github.com/gongkuihua/objc4-750-master