---恢复内容开始---
Runtime 简称运行时,系统运行时机制,主要是消息机制,OC的函数调用属于动态调用过程
Method Swizzling
用于改变已经存在的selector,在运行时改变selector在类的消息分发列表中的映射,从而改变方法的调用,这样一来如果想在不改变类的结构和方法而添加方法的情况下又多了一种方式(继承、分类、runtime)
在运行时,Class 维护了消息分发列表解决消息的正确发送,方法(Method)就是消息列表的入口,这个方法映射了一对键值对,其中键值是这个方法的名字 selector(SEL),值是指向这个方法实现的函数指针 implementation(IMP)
//获取方法列表: Method *methodList = class_copyMethodList([natural class], &count); for (NSInteger index = 0; index<count; index++) { Method method = methodList[index]; NSLog(@"method --->%@",NSStringFromSelector(method_getName(method))); } //动态添加方法: - (void)addMethod { class_addMethod([self class] , @selector(customAnimal), (IMP)customAnimal, "v@:"); [self performSelector:@selector(customAnimal)]; }
void customAnimal(id self,SEL sel){
NSLog(@"新人种");
}
动态交换方法的实现:
+(void)load{ Method imageWithName = class_getClassMethod(self, @selector(imageWithName:)); Method imageName = class_getClassMethod(self, @selector(imageNamed:)); //运行时动态交换两个方法IMP、内部实现method_getImplementation获取IMP method_setImplementation直接设置某方法IMP // * IMP imp1 = method_getImplementation(m1); // * IMP imp2 = method_getImplementation(m2); // * method_setImplementation(m1, imp2); // * method_setImplementation(m2, imp1); method_exchangeImplementations(imageWithName, imageName); } +(instancetype)imageWithName:(NSString *)name{ UIImage *image = [self imageWithName:name]; if (image == nil) { NSLog(@"加载空的图片"); }
Method swizzling 修改了类的消息分发列表使得已经存在的 selector 映射了另一个实现 implementation,同时重命名了原生方法的实现为一个新的 selector。
动态添加属性:
static const char *key = "name"; //分类添加属性 @implementation person (Property) - (NSString *)baseName{
//objc_getAssociatedObject 返回指定对象关联的key 值 return objc_getAssociatedObject(self, key); } - (void)setBaseName:(NSString *)baseName{ objc_setAssociatedObject(self, key, baseName, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } @endv
objc_setAssociatedObject:给对象设置给定Key关联值
参考:http://nshipster.cn/method-swizzling/
---恢复内容结束---