在 Objective C 中,如何通过反射找出方法的返回类型?

发布于 2024-12-05 09:07:23 字数 203 浏览 2 评论 0原文

@interface Foo : NSObject {
}

- (Bar)bar;

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

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

@interface Foo : NSObject {
}

- (Bar)bar;

At runtime, given [Foo class], how do we find out the return type of all methods Foo has?

I have been studying the Objective-C runtime API for a while now; as far as I could tell, there is no way to get the return type (i.e. Class) of a method or a property. This seems to be a serious omission in any reflection API.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

半城柳色半声笛 2024-12-12 09:07:23

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

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

Objective-C 运行时参考

首先,使用 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 );

You can use the Objective-C runtime functions:

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

Objective-C Runtime Reference

First of all, get the method object, using class_getClassMethod

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

Then, asks for the return type using method_getReturnType:

char ret[ 256 ];
method_getReturnType( m, ret, 256 );
NSLog( @"Return type: %s", ret );
浊酒尽余欢 2024-12-12 09:07:23

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

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

已经存在这样的情况:将 C++ 对象传递给 Objective-C 方法时,与方法参数化相关的元数据的数量级比生成的代码大(字面意思是单个方法调用的元数据的 MB 数) 。


参数/返回类型元数据形式的相对简单类型的示例:

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

以及来自 WebKit 的一个特别令人震惊的示例:

^{文档=^^?^^?i^{ContainerNode}{Weak=^{JSValue}}^{文档}^{节点}^{节点}^{渲染对象}I^{节点}^{节点}^{TreeScope}{DocumentOrderedMap={HashMap,WTF::HashTraits,WTF::HashTraits

<块引用>

={哈希表,WTF::PairFirstExtractor
,WTF::PtrHash,WTF::PairHashTraits,
WTF::HashTraits
,WTF::哈希特征
=^{pair}iiii}}{HashCountedSet,WTF::HashTraits
={HashMap,WTF::HashTraits,WTF::HashTraits
={哈希表,WTF::PairFirstExtractor
,WTF::PtrHash,WTF::PairHashTraits,
WTF::HashTraits
,WTF::哈希特征
=^{pair}iiii}}}}{DocumentOrderedMap={HashMap,WTF::HashTraits,WTF::HashTraits
={哈希表,WTF::PairFirstExtractor
,WTF::PtrHash,WTF::PairHashTraits,
WTF::HashTraits
,WTF::哈希特征
=^{pair}iiii}}{HashCountedSet,WTF::HashTraits
={HashMap,WTF::HashTraits,WTF::HashTraits
={哈希表,WTF::PairFirstExtractor
,WTF::PtrHash,WTF::PairHashTraits,
WTF::HashTraits
,WTF::哈希特征
=^{pair}iiii}}}}I^^?{RefPtr=^{SecurityOrigin}}{HashSet,WTF::HashTraits
={哈希表,WTF::PtrHash,WTF::HashTraits,WTF::HashTraits
=^^{MessagePort}iiii}}{HashMap,WTF::HashTraits,WTF::HashTraits
={哈希表,WTF::PairFirstExtractor
,WTF::PtrHash,WTF::PairHashTraits,
WTF::HashTraits >,WTF::HashTraits
=^{pair}iiii}}BB{HashMap,WTF::HashTraits,WTF::HashTraits
={HashTable,WTF::PairFirstExtractor>,WTF::IntHash,WTF::PairHashTraits,
WTF::HashTraits >,WTF::HashTraits
=^{pair}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}}}b 1b1iiiiiiiiii}{KURL={String={RefPtr=^{StringImpl}}}b1b1iiiiiiiiii}{KURL={String={RefPtr=^{StringImpl}}}b1b1iiiiiiiiii}{String={RefPtr=^{StringImpl}}}{String ={回复fPtr=^{StringImpl}}}{RefPtr=^{DocumentType}}{OwnPtr=^{DOMImplementation}}iBiB{RefPtr=^{CSSStyleSheet}}{RefPtr=^{CSSStyleSheet}}{RefPtr=^{CSSStyleSheet}}{自己的Ptr,
0ul>
=^{向量,0ul>}}BBBBiB{Color=IB}{RefPtr=^{节点}}{RefPtr=^{节点}}{RefPtr=^{节点}}{RefPtr=^{元素}}Q{HashSet ,WTF::哈希特征
={哈希表,WTF::PtrHash,WTF::HashTraits,WTF::HashTraits
=^^{NodeIterator}iiii}}{HashSet,WTF::HashTraits
={哈希表,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^{文档}{?=^q}}BBBBBBBBBBBBBBBBBI{StringWithDirec化={String={RefPtr=^{StringImpl}}}i}{StringWithDirection={String={RefPtr=^{StringImpl}}}i}B{RefPtr=^{Element}}{OwnPtr=^{RenderArena}} ^{AXObjectCache}{OwnPtr=^{文档MarkerController}}{Timer=^^?ddiI^{文档}{?=^q}}^{元素}B{RefPtr=^{SerializedScriptValue}}dBi{OwnPtr=^{ScriptRunner}}{OwnPtr=^{TransformSource} {RefPtr=^{文档}}i {String={RefPtr=^{StringImpl}}}{String={RefPtr=^{StringImpl}}}B{String={RefPtr=^{StringImpl}}}^{RenderObject}{RefPtr=^{TextResourceDecoder}}i {CheckedRadioButtons={OwnPtr,,
WTF::哈希特征,
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::哈希特征
=^{pair*>}iiii}}{HashMap,WTF::PtrHash,WTF::HashTraits,WTF::HashTraits*>
={HashTable,std::pair*>,WTF::PairFirstExtractor*>
,WTF::PtrHash,WTF::PairHashTraits,
WTF::HashTraits*>
,WTF::哈希特征
=^{pair*>}iiii}}BB}]}{FixedArray,
WTF::哈希特征,
WTF::HashTraits
,2ul>=[2{HashMap,WTF::HashTraits,WTF::HashTraits
={哈希表,WTF::PairFirstExtractor
,WTF::PtrHash,WTF::PairHashTraits,
WTF::HashTraits
,WTF::哈希特征
=^{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::哈希特征
=^{对
}iiii}}BB[1{IconURL=i{KURL={String={RefPtr=^{StringImpl}}}b1b1iiiiiiiiii}}]{HashSet,WTF::HashTraits
={哈希表,WTF::PtrHash,WTF::HashTraits,WTF::HashTraits
=^^{元素}iiii}}{HashSet,WTF::HashTraits
={哈希表,WTF::PtrHash,WTF::HashTraits,WTF::HashTraits
=^^{元素}iiii}}{HashSet,WTF::HashTraits
={哈希表,WTF::PtrHash,WTF::HashTraits,WTF::HashTraits
=^^{元素}iiii}}{HashMap,WTF::HashTraits
={哈希表,WTF::PairFirstExtractor
,WTF::CaseFoldingHash,WTF::PairHashTraits,
WTF::HashTraits >,WTF::HashTraits
=^{pair}iiii}}BBBBBBB{RefPtr=^{EventQueue}}{RefPtr=^{DocumentWeakReference}}{HashSet,WTF::HashTraits
={哈希表,WTF::PtrHash,WTF::HashTraits,WTF::HashTraits
=^^{MediaCanStartListener}iiii}}{QualifiedName=^{QualifiedNameImpl}}B{RefPtr=^{Element}}^{RenderFullScreen}{Timer=^^?ddiI^{文档}{?=^q}}{Deque ,0ul>=QQ{VectorBuffer,0ul>=^{RefPtr}Q}}B{IntRect={Int Point=ii}{IntSize=ii}}{RefPtr=^{RenderStyle}}i{Timer=^^?ddiI^{文档}{?=^q}}{ViewportArguments=fffffff}BB{DocumentTiming=ddddd}{RefPtr =^{MediaQueryMatcher}}BII{RefPtr=^{ContentSecurityPolicy}}}16@0:8


You can tell basic information like what C type it is, but you can't differentiate between various instance types (or classes) on the return type.

Objective-C was never designed nor intended to have that level of a reflection. Mostly because doing so would massively increase the size of the executables (all the metadata) and supporting full argument/return-type metadata introspection for all C types -- think C++ types -- would be incredibly complex.

Already, there have been cases where the metadata related to the parameterization of methods has measured in the orders of magnitude larger than the generated code when passing C++ objects to Objective-C methods (literally -- MBs for the metadata for a single method call).


An example of a relatively simple type in argument/return-type metadata form:

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

And a particularly egregious example from the 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
=^{pair}iiii}}BB{HashMap,WTF::HashTraits,WTF::HashTraits
={HashTable,WTF::PairFirstExtractor >,WTF::IntHash,WTF::PairHashTraits,
WTF::HashTraits >,WTF::HashTraits
=^{pair}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
=^^{Range}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 >
={HashTable
,WTF::PairFirstExtractor >
,WebCore::FormElementKeyHash,WTF::PairHashTraits >
,WebCore::FormElementKeyHashTraits>=^{pair
}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

={HashTable
,WTF::PairFirstExtractor >
,WTF::StringHash,WTF::PairHashTraits,
WTF::HashTraits >
,WTF::HashTraits
=^{pair
}iiii}}BB[1{IconURL=i{KURL={String={RefPtr=^{StringImpl}}}b1b1iiiiiiiiii}}]{HashSet,WTF::HashTraits
={HashTable,WTF::PtrHash,WTF::HashTraits,WTF::HashTraits
=^^{Element}iiii}}{HashSet,WTF::HashTraits
={HashTable,WTF::PtrHash,WTF::HashTraits,WTF::HashTraits
=^^{Element}iiii}}{HashSet,WTF::HashTraits
={HashTable,WTF::PtrHash,WTF::HashTraits,WTF::HashTraits
=^^{Element}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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文