iOS开发 Runtime使用大全(一)

来源:互联网 发布:怎样上淘宝网买东西 编辑:程序博客网 时间:2024/05/16 07:13

runtime,运行时。
就是说程序运行的时候可以进行操作,如调用新函数、删除已有的函数、改变变量的值等。

runtime就是实现语言动态的api
1.类的动态改变
2.消息传递
一个类的内部定义如下

struct objc_class {    Class isa  OBJC_ISA_AVAILABILITY;    #if !__OBJC2__    Class super_class;//父类    const char *name;//类名    long version;//类的版本信息,默认为0    long info;//类信息,供运行期使用的一些位标识    long instance_size;//类的实例变量大小    struct objc_ivar_list *ivars;// 类的成员变量链表    struct objc_method_list **methodLists;// 方法链表    struct objc_cache *cache;//方法缓存    struct objc_protocol_list *protocols;//协议链表#    endif}     OBJC2_UNAVAILABLE;

isa和super_class

isa:
每个实例对象都有一个isa指针,指向对象的类;
类也是一个对象,所以也有isa指针,指向元类。
元类也是对象,它的isa指针指向根元类

一个类方法被调用的时候,元类会去查自己是否有实现,没有就查父类,直到根类。

给OC对象发消息,runtime库会根据这个对象的isa指针其父类,然后在类方法列表里面寻找实现,若没有,就根据super_class寻找父类方法列表,直到根类。找到就运行这个方法

isa:实例对象-》类-》元类-》直接到根元类(NSObject的元类),根元类的isa指向自己
superclass:类-》父类-》中间类-》根类NSObject,袁元-》父元类》中间元类-》根元类-》根类;NSObject的superclass指向nil

SEL:类成员方法的指针,SEL只是保存了方法编号,不是方法的地址。
IMP:保存方法的地址
Method:方法结构体,保存方法名、实现和类型描述字符串

1.动态添加方法

//调用方法[model performSelector:@selector(Wenwen)];
//自己重写的方法- (void)addFind{    NSLog(@"Wen Cheng");}//调用不存在的实例方法时调用+ (BOOL)resolveInstanceMethod:(SEL)sel{    if ([NSStringFromSelector(sel) isEqualToString:@"Wenwen"]) {        //这一行打断点        return YES;    }    return NO;}

如果直接运行,肯定会报错的。因为我们还没有添加方法。所以在运行成功后,再断点处,使用lldb命令,进行添加:call class_addMethod(self, sel, class_getMethodImplementation([HeaderModel class], @selector(addFind)), “v@:*”);
,就可以看到打印的”Wen Cheng”

未找到方法实现时,会调用以下几个方法。

//调用不存在的类方法时调用,默认NO,加入处理再返回YES+ (BOOL)resolveClassMethod:(SEL)sel;//处理实例方法+ (BOOL)resolveInstanceMethod:(SEL)sel;//调用其它类的方法,返回有这个方法的target- (id)forwardingTargetForSelector:(SEL)aSelector;//将不存在的方法打包成NSInvocation传给你- (void)forwardInvocation:(NSInvocation *)anInvocation;
原创粉丝点击