runtime 内涵篇
1 消息发送机制
/ // ViewController.m // 001--消息机制 // // Created by H on 2017/11/2. // Copyright © 2017年 H. All rights reserved. // #import "ViewController.h" #import "Person.h" #import "HKPerson.h" #import <objc/message.h> @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; HKPerson * p = [[HKPerson alloc] init]; //给父类发消息 /* 1.objc_super 结构体指针! 2.方法编号 */ //class_getSuperclass 获取父类类型 //定义objc_super 结构体 /* struct objc_super { __unsafe_unretained _Nonnull id receiver;//当前对象 __unsafe_unretained _Nonnull Class super_class;//父类类型 }; */ //子类调用 父类方法 HKPerson调用父类person的 eatWith: 方法 struct objc_super hksuper = {p,class_getSuperclass(objc_getClass("HKPerson"))}; //给父类发消息 objc_msgSendSuper(&hksuper, @selector(eatWith:),@"汉堡"); } -(void)demo1 { //alloc :分配内存空间 malloc()用来分配内存的!! 告诉系统.给我一块空间!! // Person * p = [[Person alloc] init]; //OC的方法中: 1.SEL 方法编号 // NSClassFromString(@"Person"); //objc_getClass("Person"); // Person * p = [Person alloc]; Person * p = objc_msgSend(objc_getClass("Person"), sel_registerName("alloc")); // p = [p init]; p = objc_msgSend(p, sel_registerName("init")); // [p eatWith:@"汉堡!!"]; objc_msgSend(p, sel_registerName("eatWith:"),@"汉堡!!"); } /* 总结 发消息 objc_msgSend( id _Nullable self , SEL _Nonnull op, ... ) 1 当前对象(可以是类 就是类对象) 2 sel 方法编号 */ @end
2 动态添加方法 防止程序崩溃
// // Person.m // 004--动态添加方法 // // Created by H on 2017/11/2. // Copyright © 2017年 H. All rights reserved. // #import "Person.h" #import <objc/runtime.h> @implementation Person /* OC的方法调用,会传递默认两个隐世参数!给IMP(方法实现)!! objc_msgSend(self,_cmd); id self 方法调用者! SEL _cmd 方法编号! */ //如果该类接收到一个没有实现的实例方法,就会来到这里 +(BOOL)resolveInstanceMethod:(SEL)sel { // NSLog(@"%@",NSStringFromSelector(sel)); //动态添加一个方法!! /* 1.cls 调用方法所属类 Class _Nullable __unsafe_unretained cls 2.SEL 方法名称(方法编号) SEL _Nonnull name (sel--imp一一对应) 3.IMP 方法实现的指针 IMP _Nonnull imp 4.types 返回值类型! const char * _Nullable types */ // class_addMethod(Class _Nullable __unsafe_unretained cls, SEL _Nonnull name, IMP _Nonnull imp, const char * _Nullable types) class_addMethod(self, sel, (IMP)haha, "v@:@"); return [super resolveInstanceMethod:sel]; } void haha(id obj,SEL sel,NSString * objc){ NSLog(@"%@--%@--%@",obj,NSStringFromSelector(sel),objc); } /* 总结: 1 view调用 person方 eat:方法 但是Person并没有实现这个方法 [p performSelector:@selector(eat:) withObject:@"汉堡!!"]; 2 Person类 在runtime中 如果方法找不到会调用 +(BOOL)resolveInstanceMethod:(SEL)sel(仅仅实例方法) 3 方案 动态添加方法 void haha(id obj,SEL sel,NSString * objc){} 注意 为什么 不是 void haha(NSString * objc){} 因为 objc_msgSend(self,_cmd); 消息接受者/方法编号 传递给imp(指向函数的指针) 所以 加上字符串参数 一共是三个 */ @end