
1.数据结构
(1)objc_object

(2)objc_class

(3)isa指针

什么是isa指针?
isa分为指针型isa,isa的值代表class地址,非指针型isa的值的部分代表class的地址。
(4)isa指向
- 关于
对象
,其指向类对象
截图4.png
- 关于
类对象
,其指向元类对象
截图5.png
(5) catch_t
- 用于快速查找方法执行的函数。
- 可
可增量扩展
的哈希表
结构 - 是
局部性原理的
最佳应用
其数据结构
如下图
截图6.png
(6) class_data_bits_t
-
class_data_bits_t
主要是对class_rw_t
的封装 -
class_rw_t
代表了类相关的读写
信息,对class_ro_t的封装
(7) class_rw_t

(8) class_ro_t

(9) method_t

Type Encodings
- const char * types
截图10.png
整体数据结构
图11.png
2.对象、类对象、元类对象
-
类对象
存储实例方法列表等信息 -
元类对象
存储类方法列表等信息
截图12.png
类对象和元类对象之间有什么区别和联系?
实例对象可以通过isa指针
找到类对象,从而找到类对象中存储的实例方法列表等信息,类对 象可以通过isa指针
找到元类对象,从而找到元类对象中存储的类方法列表等信息,类对象和元类对象都是objc_class
这种数据结构的。对于任何一个元类对象,它的isa指针都指向根元类对象。根元类对象的superClass指针指向根类对象。
思考
调用一个类方法,会沿着元类对象及其元类对象的父类的方法列表依次查找,当类方法在元类对象中找不到时,就会找根类对象中,同名的实例方法实现。
消息传递过程
调用实例方法, 首先系统会根据当前实例的isa指针,找到对应的类对象,在类对象及其父类的方法列表中依次查找,直到找到根类对象,如果还是没用找到,就会走到消息的转发流程。
调用类方法,系统会根据当前类的isa指针,找到对应的元类对象,在元类对象及其元类对象的父类方法列表中依次查找,直到找到根元类,如果根元类中也没有,就会到根类对象中查找同名的实例方法,如果最终还是没找到就会走到消息的转发流程。
3.消息传递



#import "Phone.h"
@implementation Phone
- (instancetype)init{
self = [super init];
if (self) {
NSLog(@"%@",NSStringFromClass([self class]));
NSLog(@"%@",NSStringFromClass([super class]));
}
return self;
}
@end
最终的打印结构是一致的,都是Phone
(1)缓存查找
给定值SEL
,目标值是对应bucket_t
中的IMP

首先根据方法选择器,通过一个函数映射出bucket_t在数组中的位置,这一步骤涉及到哈希查找。哈希查找就是根据给定的一个值,然后经过哈希函数的算法算出的值,就是给定的值的在数组中的索引位置。
(2)当前类中查找
- 对于
已排序好
的列表,采用二分查找
算法查找方法对应执行函数。 - 对于
没有排序
的列表,采用一般遍历
查找方法对应执行函数。
(3)父类逐级查找

4.消息转发

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
RuntimeObject *obj = [[RuntimeObject alloc] init];
[obj test];
return YES;
}
#import <Foundation/Foundation.h>
@interface RuntimeObject : NSObject
- (void)test;
@end
#import "RuntimeObject.h"
@implementation RuntimeObject
+ (BOOL)resolveInstanceMethod:(SEL)sel{
//如果test方法 打印日志
if (sel == @selector(test)) {
NSLog(@"resolveInstanceMethod:");
return NO;
}else{
return [super resolveInstanceMethod:sel];
}
}
- (id)forwardingTargetForSelector:(SEL)aSelector{
NSLog(@"forwardingTargetForSelector");
return nil;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
if (aSelector == @selector(test)) {
NSLog(@"methodSignatureForSelector");
// v代表返回值是void类型 @代表第一个参数类型是id,即self
// : 代表第二个参数是SEL类型的,即@selector(test)
return [NSMethodSignature signatureWithObjCTypes:"v@:"];
}else{
return [super methodSignatureForSelector:aSelector];
}
}
- (void)forwardInvocation:(NSInvocation *)anInvocation{
NSLog(@"forwardInvocation");
}
打印结果:

5.Method-Swizzling

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
RuntimeObject *obj = [[RuntimeObject alloc] init];
[obj test];
return YES;
}
#import <Foundation/Foundation.h>
@interface RuntimeObject : NSObject
- (void)test;
- (void)otherTest;
@end
#import "RuntimeObject.h"
#import <objc/runtime.h>
@implementation RuntimeObject
+ (void)load{
//获取test方法
Method test = class_getInstanceMethod(self, @selector(test));
//获取otherTest
Method otherTest = class_getInstanceMethod(self, @selector(otherTest));
//交换两个方法的实现
method_exchangeImplementations(test, otherTest);
}
- (void)test{
NSLog(@"test");
}
- (void)otherTest{
//实际上调用test的具体实现
[self otherTest];
NSLog(@"otherTest");
}
+ (BOOL)resolveInstanceMethod:(SEL)sel{
//如果test方法 打印日志
if (sel == @selector(test)) {
NSLog(@"resolveInstanceMethod:");
return NO;
}else{
return [super resolveInstanceMethod:sel];
}
}
- (id)forwardingTargetForSelector:(SEL)aSelector{
NSLog(@"forwardingTargetForSelector");
return nil;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
if (aSelector == @selector(test)) {
NSLog(@"methodSignatureForSelector");
// v代表返回值是void类型 @代表第一个参数类型是id,即self
// : 代表第二个参数是SEL类型的,即@selector(test)
return [NSMethodSignature signatureWithObjCTypes:"v@:"];
}else{
return [super methodSignatureForSelector:aSelector];
}
}
- (void)forwardInvocation:(NSInvocation *)anInvocation{
NSLog(@"forwardInvocation");
}
@end
打印结果

6.动态添加方法
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
RuntimeObject *obj = [[RuntimeObject alloc] init];
[obj test];
return YES;
}
#import <Foundation/Foundation.h>
@interface RuntimeObject : NSObject
- (void)test;
@end
#import "RuntimeObject.h"
#import <objc/runtime.h>
@implementation RuntimeObject
void testImp(void)
{
NSLog(@"test invoke");
}
+ (BOOL)resolveInstanceMethod:(SEL)sel{
//如果test方法 打印日志
if (sel == @selector(test)) {
NSLog(@"resolveInstanceMethod:");
class_addMethod(self, @selector(test),testImp,"v@:");
return YES;
}else{
return [super resolveInstanceMethod:sel];
}
}
打印结果

网友评论