理解Runtime特性
来源:互联网 发布:常用网络端口 编辑:程序博客网 时间:2024/06/16 12:04
Objective-C 使用运行时机制,即在程序运行时才决定执行的方法对方法进行调用,其中最主要的是一套消息发送机制。使用C语言实现,方法包含在头文件#import<objc/objc-runtime.h>中,里面包含很多运行时方法。
1.如我们常规的一条方法调用:[object addDanmicMethod],会在编译时被翻译成objc_msgSend(object,@selector(addDanmicMethod));每一个class包含一个is指针,还有一个dispatch_table(分发表)存放所有成员方法的入口。
这个方法先去查找 self这个对象或者其父类是否响应 @selector(addDanmicMethod),如果从这个类的方法分发表或者 cache里面找到了,就调用它对应的函数指针。如果找不到,那就会执行一些其他的东西。步骤如下:
- 检测这个 selector是不是要忽略的。比如 Mac OS X 开发,有了垃圾回收就不理会 retain, release这些函数了。
- 检测这个 target是不是 nil 对象。ObjC的特性是允许对一个 nil 对象执行任何一个方法不会 Crash,因为会被忽略掉。
- 如果上面两个都过了,那就开始查找这个类的 IMP,先从 cache里面找,完了找得到就跳到对应的函数去执行。
- 如果 cache找不到就找一下方法分发表。
- 如果还找不到就要开始消息转发逻辑了。
这种消息转发机制是 Runtime非常重要的一个特性,大概的步骤如下:
1.查找该类及其父类的 cahce 和方法分发表,在找不到的情况下执行2。
2.执行 + (BOOL) resolveInstanceMethod:(SEL)aSEL 方法。这就给了程序员一次机会,可以告诉 runtime 在找不到改方法的情况下执行什么方法。举个例子:
-(NSString *)setaddFunction:(NSString *)string1 withValue:(NSString *)string2
{
return [string1stringByAppendingString:string2];
}
NSString* myDaynamicIMP(id self,SEL _cmd)
{
NSLog(@"result:%@",[self setaddFunction:@"this is an" withValue:@"daynamic method"]);
return [self setaddFunction:@"this is an" withValue:@" daynamic method"];
}
NSString* myNewDaynamicIMP(id self,SEL _cmd)
{
NSLog(@"result:%@",[self setaddFunction:@"this is an" withValue:@"daynamic replace method"]);
return [self setaddFunction:@"this is an" withValue:@" daynamic replace method"];
}
-(IBAction)clickChangeBehavior:(id)sender
{
SEL oriFunction = @selector(myDaynamicIMP);
IMP orginIMP = [NSObject instanceMethodForSelector:oriFunction];
IMP imp2 = class_replaceMethod([self class],oriFunction,(IMP)myNewDaynamicIMP,NULL);
_textView.text = [self performSelector:@selector(myDaynamicIMP)];
}
+(BOOL)resolveInstanceMethod:(SEL)sel
{
if(sel == @selector(addDanmicMethod))
{
class_addMethod([self class], sel, (IMP)myDaynamicIMP, "N@:");//动态添加一个实现方法
return YES;
}
return [super resolveInstanceMethod:sel];
}
3.接下来 Runtime 会调用 – (id)forwardingTargetForSelector:(SEL)aSelector 方法。这就给了程序员第二次机会,如果你没办法在自己的类里面找到替代方法,你就重载这个方法,然后把消息转给其他的Object。
-(id)forwardingTargetForSelector:(SEL)aSelector
{
if(aSelector == @selector(addDanmicMethod))
{
return [self setaddFunction:@"this is an" withValue:@" daynamic forward method"]
}
return [self forwardingTargetForSelector:aSelector];
}
4.最后,Runtime 会调用 – (void)forwardInvocation:(NSInvocation *)anInvocation 这个方法。NSInvocation 其实就是一条消息的封装。如果你能拿到 NSInvocation,那你就能修改这条消息的 target, selector 和 arguments。举个例子:
-(void)forwardInvocation:(NSInvocation *)invocation{
SEL invSEL = invocation.selector;
if([altObject respondsToSelector:invSEL]) {
[invocation invokeWithTarget:altObject];
} else {
[self doesNotRecognizeSelector:invSEL];
}
}
默认情况下 NSObject 对 forwardInvocation 的实现就是简单地执行 -doesNotRecognizeSelector: 这个方法,所以如果你想真正的在最后关头去转发消息你可以重载这个方法。
- 理解Runtime特性
- runtime理解
- Runtime 理解
- runtime理解
- runtime理解
- runtime 理解
- runtime理解
- Objective-C特性:Runtime
- Objective-C特性:Runtime
- Objective-C特性:Runtime
- Objective-C特性:Runtime
- Objective-C特性:Runtime
- C Runtime Library 理解
- Windows Runtime Component理解
- runtime的个人理解
- 理解runtime system
- runtime 中OC理解
- 关于runtime的理解
- 360网盘做svn的方法
- (function() {})();只执行一次
- Linux sort,uniq,cut,wc命令详解
- iOS 各种控件默认高度
- Path路径相关操作
- 理解Runtime特性
- 关于android的pulltorefreshview组件在视图页面无法显示的问题
- Oracle左连接,右连接
- 正则表达式速查表
- EJB必须掌握的概念
- 消息队列之JMS和AMQP对比
- MYSQL添加远程用户或允许远程访问三种方法
- 手把手教你:Ubuntu14+apache2+django1.7+python2.7下网页/网站部署
- Java Web利用POI导出Excel简单例子