runtime,直译的意思就是运行时,这是iOS开发中很重要的一个概念,其本质就是消息发送机制,是iOS开发中的一个黑魔法。众所周知,OC在编译阶段,不管是否有实现这个方法,都可通过编译,这就给开发者留下了很大的空间,可以利用黑魔法,在函数执行的时候动态做一些事情。下面就是我学习runtime的一点记录。
本文介绍runtime的常用方法,包括动态获取一个对象的成员变量、属性、方法以及遵守的协议。下面是实例代码。
使用runtime需要引入头文件"objc/runtime.h"
#import <Foundation/Foundation.h>
#import "ProtocolModel.h"
@interface Person : NSObject<ProtocalA,ProtocalB>
@property (nonatomic,strong) NSString *name;
@property (nonatomic,assign) NSInteger age;
-(NSString *) getName;
-(NSInteger) getAge;
+(void) testMethod;
@end
#import "Person.h"
@implementation Person
-(NSString *) getName{
return @"I am Lilei";
}
-(NSInteger) getAge{
return 25;
}
+(void) testMethod{
NSLog(@"This is a test class method");
}
-(NSString *)personDescribe
{
return [NSString stringWithFormat:@"name=%@,age=%ld",_name,_age];
}
@end
#import <Foundation/Foundation.h>
@protocol ProtocalA <NSObject>
-(void) showA;
@end
@protocol ProtocalB <NSObject>
-(void) showB;
@end
@interface ProtocolModel : NSObject
@end
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
Person *person = [[Person alloc] init];
unsigned int count;
NSLog(@"+++++++++++++ 获取属性列表 +++++++++++++");
objc_property_t *propertyList = class_copyPropertyList([person class], &count);
for (unsigned int i = 0; i < count; i ++) {
const char *propertyName = property_getName(propertyList[i]);
NSLog(@"属性:%s",propertyName);
}
NSLog(@"+++++++++++++ 获取方法列表 +++++++++++++");
Method *methodList = class_copyMethodList([person class], &count);
for (unsigned int i = 0; i < count; i ++) {
SEL methodName = method_getName(methodList[i]);
NSLog(@"方法:%@",NSStringFromSelector(methodName));
}
NSLog(@"+++++++++++++ 获取成员变量列表 +++++++++++++");
Ivar *ivarList = class_copyIvarList([person class], &count);
for (unsigned int i = 0; i < count; i ++) {
const char *ivarName = ivar_getName(ivarList[i]);
NSLog(@"成员变量:%s",ivarName);
if(0 == i)
{
object_setIvar(person, ivarList[i], @"Han Meimei");
}
if(1 == i)
{
//此处修改NSInteger类型属性失败,有知道方法的可以评论告诉我
object_setIvar(person, ivarList[i], @23);
}
}
NSLog(@"动态变量控制:name = %@",person.name);
NSLog(@"动态变量控制:age = %ld",person.age);
NSLog(@"+++++++++++++ 获取协议列表 +++++++++++++");
__unsafe_unretained Protocol **protocolList = class_copyProtocolList([person class], &count);
for (unsigned int i = 0; i < count; i ++) {
const char *protocolName = protocol_getName(protocolList[i]);
NSLog(@"协议名:%s",protocolName);
}
//通过方法名获得类方法
Class personClass = object_getClass([Person class]);
SEL classSel = @selector(testMethod);
Method classMethod = class_getInstanceMethod(personClass, classSel);
//通过方法名获得实例方法
SEL objSel1 = @selector(getName);
Method objMethod1 = class_getInstanceMethod([person class], objSel1);
SEL objSel2 = @selector(getAge);
Method objMethod2 = class_getInstanceMethod([person class], objSel2);
//交换两个方法的实现
NSLog(@"交换前-------%@,%ld",[person getName],[person getAge]);
//由于方法的返回类型不一致,程序运行到此处会失败,这里只是介绍使用方法
method_exchangeImplementations(objMethod1, objMethod2);
NSLog(@"交换后-------%@,%ld",[person getName],[person getAge]);
}