Objective-C Runtime能做什么?

之前的文章中我们介绍了Runtime是什么,属于理论性介绍,你看了上篇很迫切的想知道Runtime到底能干什么?不要着急,这一篇Blog将将讲解Runtime怎么应用到实战中Runtime官方文档在这里,包括了接口名字以及使用说明。下文讲到的接口都能在此文档中找到。

KVC中setValue中使用

我们知道在KVC中如果直接setValue如果对象没有这个属性或者是变量就会直接Crash,如:

RuntimeObj *obj = [[RuntimeObj alloc]init];

[obj setValue:@"value4Name"forKey:@"objName"];//RuntimeObj 没有objName这个属性

这段代码会直接Crash

有没有对这个感觉头疼,要是能先用某种方式检查下再set那就不会Crash? 没错,这件事情Runtime能做到

先看一下示例代码吧:

-(BOOL)hasAttribute:(NSString *)attName

{

BOOL flag = NO;

u_int               count;

Ivar *ivars = class_copyIvarList([selfclass], &count);

for(inti = 0; i < count ; i++)

{

constchar* propertyName = ivar_getName(ivars[i]);

NSString *strName = [NSString  stringWithCString:propertyName encoding:NSUTF8StringEncoding];

if([attName isEqualToString:strName]) {

flag = YES;

}

NSLog(@"===%@",strName);

}

returnflag;

}

没错,这个函数就是能帮你检查是否有某个属性或变量,下面讲解下一个代码:

*Ivar原型是typedef struct objc_ivar *Ivar;

*class_copyIvarList返回的是某个类所有属性或变量原型Ivar *class_copyIvarList(Class cls, unsigned int *outCount)

*ivar_getName返回的是没有 Ivar 结构体的名字,即变量的名字 原型const char *ivar_getName(Ivar v);

* 与这个对应的还有一个函数class_copyPropertyListclass_copyIvarList不同点在前者只取属性(@property申明的属性) 后者所有的 包括在interface大括号中申明的。

class_copyPropertyList使用的示例代码如下:

objc_property_t*    properties= class_copyPropertyList([selfclass], &count);

for(inti = 0; i < count ; i++)

{

constchar* propertyName = property_getName(properties[i]);

NSString *strName = [NSString  stringWithCString:propertyName encoding:NSUTF8StringEncoding];

NSLog(@"===%@",strName);

}

两个不同可以用代码来演示的,具体代码自己动手写 我就不贴出来,看看两者到底有什么区别?

有了这一步 你还担心滥用KVC时崩溃了么?

动态创建函数

有时候会根据项目需求动态创建某个函数,没错Runtime完全能做到

先看代码:

voiddynamicMethod(id self, SEL _cmd)

{

printf("SEL %s did not exist\n",sel_getName(_cmd));

}

+ (BOOL) resolveInstanceMethod:(SEL)aSEL

{

class_addMethod([selfclass], aSEL, (IMP)dynamicMethod,"v@:");

returnYES;

}

voiddynamicMethod(id self, SEL _cmd)

{

printf("SEL %s did not exist\n",sel_getName(_cmd));

}

+ (BOOL) resolveInstanceMethod:(SEL)aSEL

{

class_addMethod([selfclass], aSEL, (IMP)dynamicMethod,"v@:");

returnYES;

}

测试代码:

RuntimeObj *obj = [[RuntimeObj alloc]init];

[obj performSelector:@selector(dynamicMethod:)];

看看代码运行效果

讲解:

* + (BOOL) resolveInstanceMethod:(SEL)aSEL是在调用此类方法时,如果没有这个方法就会掉这个函数。

* class_addMethod就是动态给类添加方法 原型BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)

注:IMP 是函数指针

* “v@:” 是参数的一种写法 以后会做详细讲解

替换已有函数

在混合编码的时候不能按照已有思路执行原来的函数,那我们把它替换掉不就好了嘛,看Runtime是怎么做到的?

先上代码:(注讲下面的代码是为了讲targetReplaceMethod 替换成 demoReplaceMethod)

voiddemoReplaceMethod(id SELF, SEL _cmd)

{

NSLog(@"demoReplaceMethod");

}

-(void)replaceMethod

{

Class strcls = [selfclass];

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”);这句话就没有执行 被替换掉了!

注:

1.class_replaceMethod方法就是动态替换Method的函数,原型IMP

2.class_replaceMethod(Class cls, SEL name,IMP imp, const char *types)返回值就是一个新函数的地址(IMP指针)。

3. 在实际项目中会经常用到这种方式, 比如:iOS 7以及7以下绘制NavigationBar, 自己慢慢体会吧。

动态挂载对象

挂载这个词语大家应该并不陌生吧,但是在这里有一点点微妙的不同,在这里博主也不是很好解释这个词语到底什么含义,那我来举个例子吧

如:如果你在对象传递(传参)的时候需要用到某个属性,按照以往的思路:我继承这个类重新一个新类就完事了,OK,这个思路没有问题,但是你不觉得要新建一个.h和一个.m文件有点麻烦?程序员都是懒惰的,要是有一个方法能直接讲我想要的属性挂载上前去岂不是更好?代码简单、易懂。看了标题你就应该知道Runtime能帮你实现你的愿望。

下面就来讲解下如何使用Runtime来 在已有对象上动态挂载另外一个对象。

先不说 直接放代码(这里以UIAlertView为例子):

//挂载对象所需要的参数(UIAlertView挂载对象)

staticconstcharkRepresentedObject;

-(void)showAlert:(id)sender

{

UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"提示"message:message delegate:self cancelButtonTitle:@"取消"otherButtonTitles:@"去看看", nil];

alert.tag = ALERT_GOTO_TAG;

objc_setAssociatedObject(alert, &kRepresentedObject,

@"我是被挂载的",

OBJC_ASSOCIATION_RETAIN_NONATOMIC);

[alert show];

}

这个只是挂载看看如何去获取我们挂载的对象(NSString @“我是被挂载的”)

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex

{

if(buttonIndex == 1) {

NSString *str = objc_getAssociatedObject(alertView,

&kRepresentedObject);

NSLog(@"%@",str)

}

}

自己动手编写代码看看效果 是不是和你想的一样?

下面讲解下:

1.static const char kRepresentedObject;这个只是一个标记,但是必不可少 具体什么作用没做过调研,我觉得应该就是你挂载的一个标记Runtime应该会根据这个标记来区别被挂载对象是挂载在哪个实例上。

2.objc_setAssociatedObject动态设置关联对象(也就是挂载)。

3.objc_getAssociatedObject动态获取关联对象 看到没有这里也要传kRepresentedObject这个标记,好像有点证明我前面的猜想了。

更多接口见官方文档

推荐阅读:详解Objective-C runtime

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,904评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,581评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,527评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,463评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,546评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,572评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,582评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,330评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,776评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,087评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,257评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,923评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,571评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,192评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,436评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,145评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容