Objective-C 扩展了 C 语言,并加入了面向对象特性和 Smalltalk 式的消息传递机制。而这个扩展的核心是一个用 C 和 编译语言 写的 Runtime 库。它是 Objective-C 面向对象和动态机制的基石。
Objective-C 是一个动态语言,这意味着它不只须要一个编译器,也须要一个运行时系统来动态得建立类和对象、进行消息传递和转发。理解 Objective-C 的 Runtime 机制能够帮咱们更好的了解这个语言,适当的时候还能对语言进行扩展,从系统层面解决项目中的一些设计或技术问题。了解 Runtime ,要先了解它的核心 - 消息传递 (Messaging)。
//类 struct objc_class { Class _Nonnull isa OBJC_ISA_AVAILABILITY; #if !__OBJC2__ Class _Nullable super_class OBJC2_UNAVAILABLE; const char * _Nonnull name OBJC2_UNAVAILABLE; long version OBJC2_UNAVAILABLE; long info OBJC2_UNAVAILABLE; long instance_size OBJC2_UNAVAILABLE; struct objc_ivar_list * _Nullable ivars OBJC2_UNAVAILABLE; struct objc_method_list * _Nullable * _Nullable methodLists OBJC2_UNAVAILABLE; struct objc_cache * _Nonnull cache OBJC2_UNAVAILABLE; struct objc_protocol_list * _Nullable protocols OBJC2_UNAVAILABLE; #endif } OBJC2_UNAVAILABLE;
struct objc_class { Class _Nonnull isa OBJC_ISA_AVAILABILITY; #if !__OBJC2__ Class _Nullable super_class OBJC2_UNAVAILABLE; const char * _Nonnull name OBJC2_UNAVAILABLE; long version OBJC2_UNAVAILABLE; long info OBJC2_UNAVAILABLE; long instance_size OBJC2_UNAVAILABLE; struct objc_ivar_list * _Nullable ivars OBJC2_UNAVAILABLE; struct objc_method_list * _Nullable * _Nullable methodLists OBJC2_UNAVAILABLE; struct objc_cache * _Nonnull cache OBJC2_UNAVAILABLE; struct objc_protocol_list * _Nullable protocols OBJC2_UNAVAILABLE; #endif } OBJC2_UNAVAILABLE;
struct objc_class结构体定义了不少变量,经过命名不难发现,html
/// Represents an instance of a class. struct objc_object { Class isa OBJC_ISA_AVAILABILITY; }; /// A pointer to an instance of a class. typedef struct objc_object *id;
类对象中的元数据存储的都是如何建立一个实例的相关信息,那么类对象和类方法应该从哪里建立呢?git
就是从isa指针指向的结构体建立,类对象的isa指针指向的咱们称之为元类(metaclass),github
经过上图咱们能够看出整个体系构成了一个自闭环,struct objc_object结构体实例它的isa指针指向类对象,编程
元类(Meta Class)是一个类对象的类。缓存
struct objc_method { SEL _Nonnull method_name OBJC2_UNAVAILABLE; char * _Nullable method_types OBJC2_UNAVAILABLE; IMP _Nonnull method_imp OBJC2_UNAVAILABLE; } OBJC2_UNAVAILABLE;
Method和咱们平时理解的函数是一致的,就是表示可以独立完成一个功能的一段代码,好比:这段代码,就是一个函数。数据结构
Objc.h /// An opaque type that represents a method selector.表明一个方法的不透明类型 typedef struct objc_selector *SEL;
objc_msgSend函数第二个参数类型为SEL,它是selector在Objective-C中的表示类型(Swift中是Selector类)。selector是方法选择器,能够理解为区分方法的 ID,而这个 ID 的数据结构是SEL:并发
/// A pointer to the function of a method implementation. 指向一个方法实现的指针 typedef id (*IMP)(id, SEL, ...); #endif
就是指向最终实现程序的内存地址的指针。app
name:是指 class_name 而不是 category_name。
cls:要扩展的类对象,编译期间是不会定义的,而是在Runtime阶段经过name对 应到对应的类对象。
instanceMethods:category中全部给类添加的实例方法的列表。
classMethods:category中全部添加的类方法的列表。
protocols:category实现的全部协议的列表。
instanceProperties:表示Category里全部的properties,这就是咱们能够经过objc_setAssociatedObject和objc_getAssociatedObject增长实例变量的缘由,不过这个和通常的实例变量是不同的。
从上面的category_t的结构体中能够看出,分类中能够添加实例方法,类方法,甚至能够实现协议,添加属性,不能够添加成员变量。框架
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. //执行foo函数 [self performSelector:@selector(foo:)]; } + (BOOL)resolveInstanceMethod:(SEL)sel { if (sel == @selector(foo:)) {//若是是执行foo函数,就动态解析,指定新的IMP class_addMethod([self class], sel, (IMP)fooMethod, "v@:"); return YES; } return [super resolveInstanceMethod:sel]; } void fooMethod(id obj, SEL _cmd) { NSLog(@"Doing foo");//新的foo函数 }
打印结果:2018-04-01 12:23:35.952670+0800 ocram[87546:23235469] Doing foo
#import "ViewController.h" #import "objc/runtime.h" @interface Person: NSObject @end @implementation Person - (void)foo { NSLog(@"Doing foo");//Person的foo函数 } @end @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. //执行foo函数 [self performSelector:@selector(foo)]; } + (BOOL)resolveInstanceMethod:(SEL)sel { return YES;//返回YES,进入下一步转发 } - (id)forwardingTargetForSelector:(SEL)aSelector { if (aSelector == @selector(foo)) { return [Person new];//返回Person对象,让Person对象接收这个消息 } return [super forwardingTargetForSelector:aSelector]; } @end
打印结果:2018-04-01 12:45:04.757929+0800 ocram[88023:23260346] Doing foo
#import "ViewController.h" #import "objc/runtime.h" @interface Person: NSObject @end @implementation Person - (void)foo { NSLog(@"Doing foo");//Person的foo函数 } @end @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. //执行foo函数 [self performSelector:@selector(foo)]; } + (BOOL)resolveInstanceMethod:(SEL)sel { return YES;//返回YES,进入下一步转发 } - (id)forwardingTargetForSelector:(SEL)aSelector { return nil;//返回nil,进入下一步转发 } - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { if ([NSStringFromSelector(aSelector) isEqualToString:@"foo"]) { return [NSMethodSignature signatureWithObjCTypes:"v@:"];//签名,进入forwardInvocation } return [super methodSignatureForSelector:aSelector]; } - (void)forwardInvocation:(NSInvocation *)anInvocation { SEL sel = anInvocation.selector; Person *p = [Person new]; if([p respondsToSelector:sel]) { [anInvocation invokeWithTarget:p]; } else { [self doesNotRecognizeSelector:sel]; } } @end
打印结果:2018-04-01 13:00:45.423385+0800 ocram[88353:23279961] Doing foo