2014-06-27 27 views
7

我知道在调整方法上有无数的资源。但是,是否可以通过私有API调整方法?问题是没有头文件。我想从PrivateFramework中的私有类中调用方法,例如(随机示例)Message.framework方法调整私有框架的方法iOS API

这是用于个人测试,我明白它会被Apple拒绝而被遗忘。

+0

采取

代码私人的API,你觉得你需要头文件,你可以逆向工程。看看像'class-dump'或'class-dump-z'这样的工具。很多人也在网上发布了反向工程头文件。然后,将该标题作为源文件包含在项目中。如果您遇到反向工程头文件不编译的问题,通常您只需手动检查它们,并删除不需要的'#imports',或者只是修剪头文件以仅包含函数,重新感兴趣。 – Nate

+0

这就是我最初的做法,并认为必须有一个更简单的方法。无论如何,我可以调整这个私人API谢谢布赖恩(见下文)。问题在于其他框架无法调整。即如果我直接从我的测试代码中调用该方法,我会得到调整后的函数,但如果在某个其他框架中调用了该方法,则它不会调用我的调整函数。 –

+0

您可能需要发布一个新的后续问题。另外,请具体说明。你知道哪些API会变得很有用,你是说当你的应用程序的进程中调用了API,但是直接由框架调用(而不是你的代码),那么调整不起作用? – Nate

回答

9

您可以使用NSClassFromString获取Class并使用运行时库执行方法调整。不需要头文件。你只需要知道类名和方法签名。

sel_getUid时,可以使用@selector(somePrivateMethod)给你的错误有关somePrivateMethod是无效的选择。如果你曾经试图做任何事情(因为头不可用)从my Xcode plugin

SEL sel = sel_getUid("codeDiagnosticsAtLocation:withCurrentFileContentDictionary:forIndex:"); 
Class IDEIndexClangQueryProviderClass = NSClassFromString(@"IDEIndexClangQueryProvider"); 

Method method = class_getInstanceMethod(IDEIndexClangQueryProviderClass, sel); 
IMP originalImp = method_getImplementation(method); 

IMP imp = imp_implementationWithBlock(^id(id me, id loc, id dict, IDEIndex *idx) { 
    id ret = ((id (*)(id,SEL,id,id,id))originalImp)(me, sel, loc, dict, idx); 

    // do work 

    return ret; 
}); 

method_setImplementation(method, imp); 
+0

它编译,但不搅拌我想要的方法... –

+0

发生了什么?还要确保这些代码确实运行...把它放在'+ [加载]' –

+0

代码肯定正在运行。但是,为了验证这一点,我可以调用私有API并查看它是调用原始方法还是调用原始方法。我尝试了这一点,我得到:“无法识别的选择器发送到类”这意味着我的私人api根本没有被调用。我使用了声明的类,例如:[IDEIndexClangQueryProviderClass codeDiagnosticsAtLocation:0 withCurrentFileContentDictionary:0 forIndex:NULL] –

0

在该类上创建一个类别并为要调用的方法添加声明。然后你可以实例化一个类的实例并调用该方法。

这也适用于单元测试代码中的私有方法。

+0

我不想添加一个方法,我试图替换一个方法..你是否暗示声明该方法将取代现有的方法? –

+0

声明该方法将提供访问方法来调整它。在这个问题上,投诉是没有标题方法。通过创建一个类别,您可以有效地为您想要调整的方法创建一个标题方法。 – zaph

+0

没有理由在这里使用类别,因为这不是真正的类别,这是一个应该避免的混淆技术。如果问题在于框架是私人的,并且您没有标题,只需对标题(或您感兴趣的单个方法)进行逆向工程,然后将该标题包含在项目中。没有理由将它作为*类别*。 OP缺少私有API开发中的一项基本技术,即开发您需要的反向工程头文件。这是这类问题的标准模式。 – Nate