【问题标题】:In Objective C, how to find out the return type of a method via reflection?在Objective C中,如何通过反射找出方法的返回类型?
【发布时间】:2011-11-18 20:09:19
【问题描述】:
@interface Foo : NSObject {
}

- (Bar)bar;

在运行时,给定[Foo类],我们如何找出Foo所有方法的返回类型?

我研究 Objective-C 运行时 API 已经有一段时间了;据我所知,没有办法获得方法或属性的返回类型(即类)。这似乎是任何反射 API 中的严重遗漏。

【问题讨论】:

    标签: objective-c reflection runtime introspection


    【解决方案1】:

    您可以使用 Objective-C 运行时函数:

    Method class_getClassMethod(Class aClass, SEL aSelector)
    void method_getReturnType(Method method, char *dst, size_t dst_len)
    

    Objective-C Runtime Reference

    首先,获取方法对象,使用class_getClassMethod

    Method m = class_getClassMethod( [ SomeClass class ], @selector( someMethod ) );
    

    然后,使用method_getReturnType 询问返回类型:

    char ret[ 256 ];
    method_getReturnType( m, ret, 256 );
    NSLog( @"Return type: %s", ret );
    

    【讨论】:

    • 是的——很好的例子。不过,问题在于处理类型编码的所有边缘情况和潜在复杂性。
    【解决方案2】:

    您可以说出基本信息,例如它是什么 C 类型,但您无法区分返回类型上的各种实例类型(或类)。

    Objective-C 从来没有被设计过,也没有打算有这种程度的反射。主要是因为这样做会大大增加可执行文件(所有元数据)的大小,并且支持所有 C 类型(想想 C++ 类型)的完整参数/返回类型元数据自省将非常复杂。

    在某些情况下,当将 C++ 对象传递给 Objective-C 方法时,与方法参数化相关的元数据比生成的代码要大几个数量级(字面意思是——单个元数据的 MBs方法调用)。


    argument/return-type 元数据形式的一个相对简单类型的例子:

    {CGRect={CGPoint=dd}{CGSize=dd}}96@0:8@16{CGRect={CGPoint=dd}{CGSize=dd}}24{CGRect={CGPoint=dd}{CGSize=dd}}56q88
    

    还有一个来自 WebKit 的特别令人震惊的例子:

    ^{Document=^^?^^?i^{ContainerNode}{Weak=^{JSValue}}^{Document}^{Node}^{Node}^{RenderObject}I^{Node}^{Node }^{TreeScope}{DocumentOrderedMap={HashMap,WTF::HashTraits,WTF::HashTraits

    ={HashTable,WTF::PairFirstExtractor ,WTF::PtrHash,WTF::PairHashTraits, WTF::HashTraits ,WTF::HashTraits =^{pair}iiii}}{HashCountedSet,WTF::HashTraits ={HashMap,WTF::HashTraits,WTF::HashTraits ={HashTable,WTF::PairFirstExtractor ,WTF::PtrHash,WTF::PairHashTraits, WTF::HashTraits ,WTF::HashTraits =^{pair}iiii}}}}{DocumentOrderedMap={HashMap,WTF::HashTraits,WTF::HashTraits ={HashTable,WTF::PairFirstExtractor ,WTF::PtrHash,WTF::PairHashTraits, WTF::HashTraits ,WTF::HashTraits =^{pair}iiii}}{HashCountedSet,WTF::HashTraits ={HashMap,WTF::HashTraits,WTF::HashTraits ={HashTable,WTF::PairFirstExtractor ,WTF::PtrHash,WTF::PairHashTraits, WTF::HashTraits ,WTF::HashTraits =^{pair}iiii}}}}I^^?{RefPtr=^{SecurityOrigin}}{HashSet,WTF::HashTraits ={HashTable,WTF::PtrHash,WTF::HashTraits,WTF::HashTraits =^^{MessagePort}iiii}}{HashMap,WTF::HashTraits,WTF::HashTraits ={HashTable,WTF::PairFirstExtractor ,WTF::PtrHash,WTF::PairHashTraits, WTF::HashTraits >,WTF::HashTraits =^{对}iiii}}BB{HashMap,WTF::HashTraits,WTF::HashTraits ={HashTable,WTF::PairFirstExtractor >,WTF::IntHash,WTF::PairHashTraits, WTF::HashTraits >,WTF::HashTraits =^{对}iiii}}B{OwnPtr, 0ul> =^{Vector,0ul>}}{RefPtr=^{DatabaseThread}}Bi{OwnPtr=^{CSSStyleSelector}}BB{RefPtr=^{CSSPrimitiveValueCache}}^{Frame}{OwnPtr=^{CachedResourceLoader}}{RefPtr= ^{DocumentParser}}B{KURL={String={RefPtr=^{StringImpl}}}b1b1iiiiiiiiii}{KURL={String={RefPtr=^{StringImpl}}}b1b1iiiiiiiiii}{KURL={String={RefPtr=^ {StringImpl}}}b1b1iiiiiiiiii}{KURL={String={RefPtr=^{StringImpl}}}b1b1iiiiiiiiii}{KURL={String={RefPtr=^{StringImpl}}}b1b1iiiiiiiiii}{String={RefPtr=^{StringImpl }}}{String={RefPtr=^{StringImpl}}}{RefPtr=^{DocumentType}}{OwnPtr=^{DOMImplementation}}iBiB{RefPtr=^{CSSStyleSheet}}{RefPtr=^{CSSStyleSheet}}{RefPtr =^{CSSStyleSheet}}{OwnPtr, 0ul> =^{Vector,0ul>}}BBBBiB{Color=IB}{RefPtr=^{Node}}{RefPtr=^{Node}}{RefPtr=^{Node}}{RefPtr=^{Element}}Q{HashSet ,WTF::HashTraits ={HashTable,WTF::PtrHash,WTF::HashTraits,WTF::HashTraits =^^{NodeIterator}iiii}}{HashSet,WTF::HashTraits ={HashTable,WTF::PtrHash,WTF::HashTraits,WTF::HashTraits =^^{范围}iiii}}S{RefPtr=^{StyleSheetList}}{ListHashSet ={HashTable,WTF::ListHashSetNode,WTF::IdentityExtractor*>,WTF::ListHashSetNodeHashFunctions ,WTF::HashTraits*>,WTF::HashTraits*> =^^{ListHashSetNode}iiii}^{ListHashSetNode}^{ListHashSetNode}{OwnPtr =^{ListHashSetNodeAllocator}}}{ListHashSet ={HashTable,WTF::ListHashSetNode,WTF::IdentityExtractor*>,WTF::ListHashSetNodeHashFunctions ,WTF::HashTraits*>,WTF::HashTraits*> =^^{ListHashSetNode}iiii}^{ListHashSetNode}^{ListHashSetNode}{OwnPtr =^{ListHashSetNodeAllocator}}}{ListHashSet ={HashTable,WTF::ListHashSetNode,WTF::IdentityExtractor*>,WTF::ListHashSetNodeHashFunctions ,WTF::HashTraits*>,WTF::HashTraits*> =^^{ListHashSetNode}iiii}^{ListHashSetNode}^{ListHashSetNode}{OwnPtr =^{ListHashSetNodeAllocator}}}{HashMap,WebCore::FormElementKeyHash,WebCore::FormElementKeyHashTraits,WTF::HashTraits > ={哈希表 ,WTF::PairFirstExtractor > ,WebCore::FormElementKeyHash,WTF::PairHashTraits > ,WebCore::FormElementKeyHashTraits>=^{对 }iiii}}{Color=IB}{Color=IB}{Color=IB}{String={RefPtr=^{StringImpl}}}{String={RefPtr=^{StringImpl}}}BBiB{Timer=^^? ddiI^{Document}{?=^q}}BBBBBBBBBBBBBBBBBI{StringWithDirection={String={RefPtr=^{StringImpl}}}i}{StringWithDirection={String={RefPtr=^{StringImpl}}}i}B{RefPtr =^{Element}}{OwnPtr=^{RenderArena}}^{AXObjectCache}{OwnPtr=^{DocumentMarkerController}}{Timer=^^?ddiI^{Document}{?=^q}}^{Element}B{ RefPtr=^{SerializedScriptValue}}dBi{OwnPtr=^{ScriptRunner}}{OwnPtr=^{TransformSource}}{RefPtr=^{Document}}i{String={RefPtr=^{StringImpl}}}{String={RefPtr =^{StringImpl}}}B{String={RefPtr=^{StringImpl}}}^{RenderObject}{RefPtr=^{TextResourceDecoder}}i{CheckedRadioButtons={OwnPtr, WTF::HashTraits, WTF::HashTraits > =^{HashMap,WTF::HashTraits,WTF::HashTraits }}}{FixedArray=[10{CollectionCache=Q^{Element}IIi{HashMap,WTF::PtrHash,WTF::HashTraits,WTF::HashTraits*> ={HashTable,std::pair*>,WTF::PairFirstExtractor*> ,WTF::PtrHash,WTF::PairHashTraits, WTF::HashTraits*> ,WTF::HashTraits =^{pair*>}iiii}}{HashMap,WTF::PtrHash,WTF::HashTraits,WTF::HashTraits*> ={HashTable,std::pair*>,WTF::PairFirstExtractor*> ,WTF::PtrHash,WTF::PairHashTraits, WTF::HashTraits*> ,WTF::HashTraits =^{pair*>}iiii}}BB}]}{FixedArray, WTF::HashTraits, WTF::HashTraits ,2ul>=[2{HashMap,WTF::HashTraits,WTF::HashTraits ={HashTable,WTF::PairFirstExtractor ,WTF::PtrHash,WTF::PairHashTraits, WTF::HashTraits ,WTF::HashTraits =^{pair}iiii}}]}{RefPtr=^{XPathEvaluator}}{OwnPtr=^{SVGDocumentExtensions}}{Vector=Q{VectorBuffer=^{DashboardRegionValue}Q}}BB{HashMap,WTF::StringHash,WTF ::HashTraits,WTF::HashTraits

    ={哈希表 ,WTF::PairFirstExtractor > ,WTF::StringHash,WTF::PairHashTraits, WTF::HashTraits > ,WTF::HashTraits =^{对 }iiii}}BB[1{IconURL=i{KURL={String={RefPtr=^{StringImpl}}}b1b1iiiiiiiiii}}]{HashSet,WTF::HashTraits ={HashTable,WTF::PtrHash,WTF::HashTraits,WTF::HashTraits =^^{元素}iiii}}{HashSet,WTF::HashTraits ={HashTable,WTF::PtrHash,WTF::HashTraits,WTF::HashTraits =^^{元素}iiii}}{HashSet,WTF::HashTraits ={HashTable,WTF::PtrHash,WTF::HashTraits,WTF::HashTraits =^^{元素}iiii}}{HashMap,WTF::HashTraits ={HashTable,WTF::PairFirstExtractor ,WTF::CaseFoldingHash,WTF::PairHashTraits, WTF::HashTraits >,WTF::HashTraits =^{pair}iiii}}BBBBBBB{RefPtr=^{EventQueue}}{RefPtr=^{DocumentWeakReference}}{HashSet,WTF::HashTraits ={HashTable,WTF::PtrHash,WTF::HashTraits,WTF::HashTraits =^^{MediaCanStartListener}iiii}}{QualifiedName=^{QualifiedNameImpl}}B{RefPtr=^{Element}}^{RenderFullScreen}{Timer=^^?ddiI^{Document}{?=^q}}{Deque ,0ul>=QQ{VectorBuffer,0ul>=^{RefPtr}Q}}B{IntRect={IntPoint=ii}{IntSize=ii}}{RefPtr=^{RenderStyle}}i{Timer=^^?ddiI^ {Document}{?=^q}}{ViewportArguments=fffffff}BB{DocumentTiming=ddddd}{RefPtr=^{MediaQueryMatcher}}BII{RefPtr=^{ContentSecurityPolicy}}}16@0:8

    【讨论】:

    • 当然——将任何类型的 STL 集合作为参数传递给方法。编译器将生成一个潜在的巨大字符串来描述由定义参数的类型的任何叉积所产生的结构
    • bbum - 我真的很喜欢阅读您的回复;谢谢。您之前说过,“Objective-C 从来没有被设计过,也没有打算具有那种程度的反射。”你是怎么知道的?
    • 我从 1988 年就开始使用 Objective-C,通过电子邮件与 Brad Cox 聊天,并且曾与许多曾在某个时间点“拥有”该语言的人一起工作过。这个 SO question (stackoverflow.com/questions/2833756/…) 中有更多历史信息
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-14
    • 1970-01-01
    • 2014-07-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多