转载

IOS runtime动态运行时二

在C#、Java中有编译时多态和运行时多态,在OC中,只有运行时的多态,这与它的运行机制有关。OC中,方法的调用是通过消息的传递来进行的。在IOS runtime动态运行时一http://www.cnblogs.com/5ishare/p/4708647.html中主要大致介绍了下运行时的过程,这篇主要看下消息转发(实现多态的基础)。

一.引入

在<objc/objc-runtime.h>中有两个.h,<objc/runtime.h>和<objc/message.h>,这篇主要了解<objc/message.h>

二.消息转发

在该类中主要有3中方法 (其他几种我也不知道所以有3种):objc_msgSend、objc_msgSendSuper、method_invoke。

像objc_msgSend_stret、objc_msgSend_fpret函数返回结构体、浮点数这些需要经过CPU特殊处理,所以不用太留意。它们就是上面3种的变体,当返回的是结构体、浮点数时,会调用 _stret、_fpret这些。

三.方法的使用

在使用之前有几个注意点:

1.要引入框架<objc/objc-runtime.h>

2.直接写入运行时代码会报错需要按下图设置一下

IOS runtime动态运行时二

1).objc_msgSend

在IOS runtime动态运行时一博客中也写了oc中方法调用其实是转为objc_msgSend来实现消息转发。

2).objc_msgSendSuper

这个是将消息转发给父类。方法的第一个参数是一个objc_super类型的结构体。结构体主要包括两个变量:

1.receiver:即消息的实际接收者

2.superClass:指针当前类的父类

struct objc_super {         /// Specifies an instance of a class.        __unsafe_unretained  id receiver;         /// Specifies the particular superclass of the instance to message.        __unsafe_unretained Class super_class;      };
id objc_msgSendSuper(struct objc_super *super, SEL op, ...)

3).method_invoke

在C#多线程中有invoke,这里和C#类似,用于方法的调用。这里需要传结构体Method。可以通过runtime.h来获得类中的某个Method

method_invoke(id receiver, Method m, ...)

四、测试结果

在项目中创建了一个Father类和一个继承Father的Son。Son类重写了父类的-(NSString *)getNameWithfamily:(NSString *)family方法。

#import <Foundation/Foundation.h>  @interface Father : NSObject -(NSString *)getNameWithfamily:(NSString *)family; @end
// //  Father.m //  RunTime // //  Created by City--Online on 15/11/24. //  Copyright © 2015年 City--Online. All rights reserved. //  #import "Father.h"  @implementation Father -(NSString *)getNameWithfamily:(NSString *)family; {     return [NSString stringWithFormat:@"Father %@",family]; } @end
// //  Son.h //  RunTime // //  Created by City--Online on 15/11/24. //  Copyright © 2015年 City--Online. All rights reserved. //  #import "Father.h"  @interface Son : Father  @end
// //  Son.m //  RunTime // //  Created by City--Online on 15/11/24. //  Copyright © 2015年 City--Online. All rights reserved. //  #import "Son.h"  @implementation Son -(NSString*)getNameWithfamily:(NSString *)family {          return [NSString stringWithFormat:@"Son %@",family]; } @end

1.objc_msgSend 通过objc_msgSend调用son的getNameWithfamily:方法 返回为字符串、一个参数

Son *son=[[Son alloc]init];     NSString *name= objc_msgSend(son, @selector(getNameWithfamily:),@"Tom");     NSLog(@"%@",name);
2015-11-24 13:44:26.705 RunTime[6514:223611] Son Tom

2.objc_msgSendSuper 通过objc_msgSendSuper调用父类的方法类似[super xxxxx],主要是第一个objc_super类型的结构体.

struct objc_super objcsuper;     objcsuper.receiver=father;     objcsuper.super_class=[son superclass];          NSString *superName=objc_msgSendSuper(&objcsuper, @selector(getNameWithfamily:),@"Cui");     NSLog(@"%@",superName);
2015-11-24 13:44:26.705 RunTime[6514:223611] Father Cui

3.method_invoke

Method method= class_getInstanceMethod([Son class], @selector(getNameWithfamily:));     NSString *invokeName= method_invoke(son,method,@"Zhao");     NSLog(@"%@",invokeName);
2015-11-24 13:44:26.705 RunTime[6514:223611] Son Zhao
Method method= class_getInstanceMethod([father class], @selector(getNameWithfamily:));     NSString *invokeName= method_invoke(father,method,@"Zhao");     NSLog(@"%@",invokeName);
2015-11-24 13:51:28.288 RunTime[6546:231306] Father Zhao
正文到此结束
Loading...