运行时机制,runtime库里面包含了跟类/成员变量/方法相关的API,比如获取类里面的所有成员变量,为类动态添加成员变量,动态改变类的方法实现,为类动态添加新的方法等;
@interface UIView (parameter){
}
-(void)setCustomParame:(NSDictionary*)dic;
-(NSDictionary*)customParame;
@end
//任何继承UIView 的都可以使用传递该参数,方便调用
@implementation UIView (parameter)
static char UIViewParameterKey;
-(void)setCustomParame:(NSDictionary *)dic{
objc_setAssociatedObject(self, &UIViewParameterKey, dic, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(NSDictionary*)customParame{
return objc_getAssociatedObject(self, &UIViewParameterKey);
}
@end
获取类的所有属性,成员变量,进行其他操作,平时使用到的地方有json 转model 的时候,我们需要遍历model 的所有属性,然后进行操作,用的方法class_copyIvarList
方法进行遍历,或者归档都可以;
先建一个model 类
@interface User : NSObject{
NSArray *arry;
}
@property(nonatomic,copy) NSString *name;
@property(nonatomic,copy) NSString *school;
@property(nonatomic,assign) int age;
@property(nonatomic,assign) BOOL sex;
@end
然后利用class_copyIvarList
遍历获取,
-(void)testClass_copyIvarList{
unsigned int count = 0;
Ivar *ivars=class_copyIvarList([User class], &count);
for (int i=0; i<count; i++) {
NSString * str=[NSString stringWithUTF8String:ivar_getName(ivars[i])];
NSLog(@"testtwo-------%@",str);
}
free(ivars);
}
打印结果
copyedString-0xa000000006362613,0xa000000006362613
2016-01-25 23:40:43.813 class_copyIvarlistTEST[2149:378140] testtwo-------arry
2016-01-25 23:40:43.813 class_copyIvarlistTEST[2149:378140] testtwo-------_sex
2016-01-25 23:40:43.813 class_copyIvarlistTEST[2149:378140] testtwo-------_age
2016-01-25 23:40:43.813 class_copyIvarlistTEST[2149:378140] testtwo-------_name
2016-01-25 23:40:43.813 class_copyIvarlistTEST[2149:378140] testtwo-------_school
(lldb)
还有一个方法class_copyPropertyList
是获取所有属性的方法;
Method Swizzling,有method_exchangeImplementations
交换2个方法,
@implementation UIScrollView(DataFetch)
+ (void)load
{
Method dealloc = class_getInstanceMethod([self class], NSSelectorFromString(@"dealloc"));
Method df_dealloc = class_getInstanceMethod([self class], @selector(df_dealloc));
method_exchangeImplementations(dealloc, df_dealloc);
}
还有替换已有函数class_replaceMethod
void demoReplaceMethod(id SELF, SEL _cmd)
{
NSLog(@"demoReplaceMethod");
}
-(void)replaceMethod
{
Class strcls = [self class];
SEL targetSelector = @selector(targetRelplacMethod);
class_replaceMethod(strcls,targetSelector,(IMP)demoReplaceMethod,NULL);
}
-(void)targetRelplacMethod
{
NSLog(@"targetRelplacMethod");
}
测试
RuntimeObj *obj = [[RuntimeObj alloc]init];
[obj replaceMethod];
[obj targetRelplacMethod];
打印结果
2014-05-12 19:38:37.490 Runtime[1497:303] demoReplaceMethod
是不是原来的 NSLog(@”targetRelplacMethod”); 这句话就没有执行 被替换掉了
class_replaceMethod 方法就是动态替换Method的函数,原型 IMP class_replaceMethod(Class cls, SEL name,IMP imp, const char *types) 返回值就是一个新函数的地址(IMP指针)
在实际项目中会经常用到这种方式 比如:iOS 7以及7以下绘制NavigationBar 自己慢慢体会吧
以上就是简单的rumtime 的使用,方法,其中部分参考了以下文章
http://www.anselz.com/2014/05/12/objective-c-runtime%E8%83%BD%E5%81%9A%E4%BB%80%E4%B9%88%EF%BC%9F/
http://yulingtianxia.com/blog/2014/11/05/objective-c-runtime/