ObjectiveC RuntimeWord下载.docx
- 文档编号:16230780
- 上传时间:2022-11-21
- 格式:DOCX
- 页数:2
- 大小:17.99KB
ObjectiveC RuntimeWord下载.docx
《ObjectiveC RuntimeWord下载.docx》由会员分享,可在线阅读,更多相关《ObjectiveC RuntimeWord下载.docx(2页珍藏版)》请在冰豆网上搜索。
多条不同的消息也可以对应同一个方法实现。
这些都是在程序运行的时候决定的。
事实上,在编译时你写的Objective-C函数调用的语法都会被翻译成一个C的函数调用-objc_msgSend()。
比如,下面两行代码就是等价的:
[arrayinsertObject:
fooatIndex:
5];
objc_msgSend(array,@selector(insertObject:
atIndex:
),foo,5);
消息传递的关键藏于objc_object中的isa指针和objc_class中的classdispatchtable。
objc_object,objc_class以及Ojbc_method在Objective-C中,类、对象和方法都是一个C的结构体,从objc/objc.h头文件中,我们可以找到他们的定义:
structobjc_object{ClassisaOBJC_ISA_AVAILABILITY;
};
structobjc_class{ClassisaOBJC_ISA_AVAILABILITY;
#if!
__OBJC2__Classsuper_class;
constchar*name;
longversion;
longinfo;
longinstance_size;
structobjc_ivar_list*ivars;
**structobjc_method_list**methodLists**;
**structobjc_cache*cache**;
structobjc_protocol_list*protocols;
#endif};
structobjc_method_list{structobjc_method_list*obsolete;
intmethod_count;
#ifdef__LP64__intspace;
#endif/*variablelengthstructure*/structobjc_methodmethod_list[1];
structobjc_method{SELmethod_name;
char*method_types;
/*astringrepresentingargument/returntypes*/IMPmethod_imp;
objc_method_list本质是一个有objc_method元素的可变长度的数组。
一个objc_method结构体中有函数名,也就是SEL,有表示函数类型的字符串(见TypeEncoding),以及函数的实现IMP。
从这些定义中可以看出发送一条消息也就objc_msgSend做了什么事。
举objc_msgSend(obj,foo)这个例子来说:
1.首先,通过obj的isa指针找到它的class;
2.在class的methodlist找foo;
3.如果class中没到foo,继续往它的superclass中找;
4.一旦找到foo这个函数,就去执行它的实现IMP.但这种实现有个问题,效率低。
但一个class往往只有20%的函数会被经常调用,可能占总调用次数的80%。
每个消息都需要遍历一次objc_method_list并不合理。
如果把经常被调用的函数缓存下来,那可以大大提高函数查询的效率。
这也就是objc_class中另一个重要成员objc_cache做的事情-再找到foo之后,把foo的method_name作为key,method_imp作为value给存起来。
当再次收到foo消息的时候,可以直接在cache里找到,避免去遍历objc_method_list.动态方法解析和转发在上面的例子中,如果foo没有找到会发生什么?
通常情况下,程序会在运行时挂掉并抛出unrecognizedselectorsentto…的异常。
但在异常抛出前,Objective-C的运行时会给你三次拯救程序的机会:
1.Methodresolution2.Fastforwarding3.NormalforwardingMethodResolution首先,Objective-C运行时会调用+resolveInstanceMethod:
或者+resolveClassMethod:
,让你有机会提供一个函数实现。
如果你添加了函数并返回YES,那运行时系统就会重新启动一次消息发送的过程。
还是以foo为例,你可以这么实现:
voidfooMethod(idobj,SEL_cmd){NSLog(@”Doingfoo”);
}+(BOOL)resolveInstanceMethod:
(SEL)aSEL{if(aSEL==@selector(foo:
)){class_addMethod([selfclass],aSEL,(IMP)fooMethod,”v@:
”);
returnYES;
}return[superresolveInstanceMethod];
}CoreData有用到这个方法。
NSManagedObjects中properties的getter和setter就是在运行时动态添加的。
如果resolve方法返回NO,运行时就会移到下一步:
消息转发(MessageForwarding)。
PS:
iOS4.3加入很多新的runtime方法,主要都是以imp为前缀的方法,比如imp_implementationWithBlock()用block快速创建一个imp。
上面的例子可ForSelector:
(SEL)aSelector{if(aSelector==@selector(foo:
)){returnalternateObject;
}return[superforwardingTargetForSelector:
aSelector];
}只要这个方法返回的不是nil和self,整个消息发送的过程就会被重启,当然发送的对象会变成你返回的那个对象。
否则,就会继续NormalFowarding。
这里叫Fast,只是为了区别下一步的转发机制。
因为这一步不会创建任何新的对象,但下一步转发会创建一个NSInvocation对象,所以相对更快点。
Normalforwarding这一步是Runtime最后一次给你挽救的机会。
首先它会发送-methodSignatureForSelector:
消息获得函数的参数和返回值类型。
如果-methodSignatureForSelector:
返回nil,Runtime则会发出-doesNotRecognizeSelector:
消息,程序这时也就挂掉了。
如果返回了一个函数签名,Runtime就会创建一个NSInvocation对象并发送-forwardInvocation:
消息给目标对象。
NSInvocation实际上就是对一个消息的描述,包括selector以及参数等信息。
所以你可以在-forwardInvocation:
里修改传进来的NSInvocation对象,然后发送-invokeWithTarget:
消息给它,传进去一个新的目标:
-(void)forwardInvocation:
(NSInvocation*)invocation{SELsel=invocation.selector;
if([alternateObjectrespondsToSelector:
sel]){[invocationinvokeWithTarget:
alternateObject];
}else{[selfdoesNotRecognizeSelector:
sel];
}}Cocoa里很多地方都利用到了消息传递机制来对语言进行扩展,如Proxies、NSUndoManager跟ResponderChain。
NSProxy就是专门用来作为代理转发消息的;
NSUndoManager截取一个消息之后再发送;
而ResponderChain保证一个消息转发给合适的响应者。
总结Objective-C中给一个对象发送消息会经过以下几个步骤:
1.在对象类的dispatchtable中尝试找到该消息。
如果找到了,跳到相应的函数IMP去执行实现代码;
2.如果没有找到,Runtime会发送+resolveInstanceMethod:
尝试去resolve这个消息;
3.如果resolve方法返回NO,Runtime就发送-forwardingTargetForSelector:
允许你把这个消息转发给另一个对象;
4.如果没有新的目标对象返回,Runtime就会发送-methodSignatureForSelector:
和-forwardInvocation:
消息。
你可以发送-invokeWithTarget:
消息来手动转发消息或者发送-doesNotRecognizeSelector:
抛出异常。
利用Objective-C的runtime特性,我们可以自己来对语言进行扩展,解决项目开发中的一些设计和技术问题。
下一篇文章,我会介绍MethodSwizzling技术以及如何利用MethodSwizzling做Logging。
ReferenceMessageforwardingObjective-c-messagingThefasterobjc_msgSendUnderstandingobjective-cruntime(本文作者:
顾鹏)
<
ahref="
"
>
ios消息推送<
/a>
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- ObjectiveC Runtime