赞
踩
苹果公开的源代码
Runtime的源代码
Runloop的源代码
GitHub在线查看Runtime
GitHub在线查看Runloop
iOS开发:认识一下Runtime
iOS开发:Runtime常见方法
iOS开发:Runtime解决UITapGesture重复点击问题
iOS开发:Runtime解决UIButton重复点击问题
modern
” 和 “legacy
”。我们现在用的 Objective-C 2.0
采用的是现行 (Modern
) 版的 Runtime 系统,只能运行在 iOS 和 macOS 10.5 之后的 64 位程序中。而 macOS 较老的32位程序仍采用 Objective-C 1 中的(早期)Legacy
版本的 Runtime
系统。这两个版本最大的区别在于当你更改一个类的实例变量的布局时,在早期版本中你需要重新编译它的子类,而现行版就不需要。//实例对象 struct objc_object { Class isa OBJC_ISA_AVAILABILITY; //实例对象的isa指针指向他的类对象 }; //类对象 struct objc_class { Class isa OBJC_ISA_AVAILABILITY;//isa指针指向Meta Class #if !__OBJC2__ Class super_class OBJC2_UNAVAILABLE; // 父类 const char *name OBJC2_UNAVAILABLE; // 类名 long version OBJC2_UNAVAILABLE; // 类的版本信息,默认为0 long info OBJC2_UNAVAILABLE; // 类信息,供运行期使用的一些位标识 long instance_size OBJC2_UNAVAILABLE; // 该类的实例变量大小 struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; // 该类的成员变量链表 struct objc_method_list **methodLists OBJC2_UNAVAILABLE; // 方法定义的链表 struct objc_cache *cache OBJC2_UNAVAILABLE; // 方法缓存,对象接到一个消息会根据isa指针查找消息对象,这时会在method Lists中遍历,如果cache了,常用的方法调用时就能够提高调用的效率。 struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; // 协议链表 #endif } OBJC2_UNAVAILABLE; struct objc_method_list { struct objc_method_list *obsolete OBJC2_UNAVAILABLE; int method_count OBJC2_UNAVAILABLE; #ifdef __LP64__ int space OBJC2_UNAVAILABLE; #endif /* variable length structure */ struct objc_method method_list[1] OBJC2_UNAVAILABLE; } OBJC2_UNAVAILABLE; //方法 struct objc_method { SEL method_name OBJC2_UNAVAILABLE;//方法名 char *method_types OBJC2_UNAVAILABLE;//方法类型 IMP method_imp OBJC2_UNAVAILABLE;//指向方法实现的指针 } //Category struct category_t { const char *name; //是指 class_name 而不是 category_name。 classref_t cls; //要扩展的类对象,编译期间是不会定义的,而是在Runtime阶段通过name对 应到对应的类对象. struct method_list_t *instanceMethods; //category中所有给类添加的实例方法的列表。 struct method_list_t *classMethods; //category中所有添加的类方法的列表。 struct protocol_list_t *protocols; //category实现的所有协议的列表。 struct property_list_t *instanceProperties; //表示Category里所有的properties,这就是我们可以通过objc_setAssociatedObject和objc_getAssociatedObject增加实例变量的原因 };
[objc performSelector:@selector(SEL)];
方法,编译器将代码转化为objc_msgSend(receiver, selector)
。objc_msgSend
函数中,首先通过objc
的isa
指针找到objc
对应的class
,在class
中先去cache
中通过SEL
查找对应函数的 method
,如果找到则通过 method
中的函数指针跳转到对应的函数中去执行。cacha
中未找到,再去methodList
中查找,如果能找到,则将method
加入到cache
中,以方便下次查找,并通过method
中的函数指针跳转到对应的函数中去执行。methodlist
中未找到,则去superClass
中去查找,如果能找到,则将method
加入到cache中,以方便下次查找,并通过method
中的函数指针跳转到对应的函数中去执行。一个完整转发的例子:
#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
Objective-C type encodings
Code | Meaning |
---|---|
| A |
| An |
| A |
| A
|
| A |
| An |
| An |
| An |
| An |
| An |
| A |
| A |
| A C++ |
| A |
| A character string ( |
| An object (whether statically typed or typed |
| A class object ( |
| A method selector ( |
[array type] | An array |
{name=type...} | A structure |
(name=type...) | A union |
| A bit field of num bits |
| A pointer to type |
| An unknown type (among other things, this code is used for function pointers) |
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。