IOS Private API

IOS Private API

2013年01月13日 12:21:10 chengyakun11 阅读数:7136

一.基本知识

iPhone中的API除了公开的 API:Published API外(或者叫文档中记录的API:Documented API),还有两类API:私有API:Private API和未公开的API:UnPublished API(或者叫文档中未记录的API:Undocumented API)。其中私有API是指放在PrivateFrameworks框架中的API,未公开的API是指虽然放在Frameworks框架中,但是却没有在苹果的官方文档中有使用说明、代码介绍等记录的API。后两种API是有区别的,按苹果的说法,未公开的API是还不够成熟,可能还会变动的API,等完全成型了后会变成公开的API,但是目前不对其提供承诺,就是系统版本升级后可能会失效。而私有API是苹果明确不能使用的API。虽然两者有所区别,但是在具体使用方法上是类似的。

二.具体介绍
1.导出生成私有API的头文件声明
使用私有或未公开的API,首先需要导出其对应的头文件,在头文件里有相关函数的声明。
工具:
class-dump
class-dump可以从编译后的Objective-C的二进制文件中提取对应的数据结构及函数等声明。
使用方法:
为了能在任意目录下使用class-dump命令,首先建议把class-dump文件拷贝到/user/local/bin/目录下,然后就可以在任意目录下执行以下命令:

class-dump /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.0.sdk/System/Library/Frameworks/UIKit.framework/ >UIKit.h

以上命令就可以把 iPhoneSimulator3.0.Sdk中Frameworks框架里的UIKit.Framework框架的数据结构及函数声明等给提取出来,并且放在UIKit.h这个文件中,之后你就可以在这个头文件中找你需要API的声明及其使用方式。以同样的方法,就可以挨个导出你需要那个框架中的API 声明。

也可以用ericasadun写的DumpFrameworks.pl(文件中有部分注释说明)这个文件把私有框架下的API头文件全部提取出来。使用方法也是首先把class-dump文件拷贝到/user/local/bin/目录下,然后在任意一个目录下执行./DumpFrameworks.pl,然后就会在你的家目录下产生一个Headers文件夹,里面罗列了私有框架下的API头文件。

2.使用私有API

导出了私有API的头文件声明后,使用方法就比较简单了,首先在你的工程中包含进头文件,然后导入对应的框架,之后就可以类似提供了静态库的方式在我们的代码中使用这些私有API函数。


三.附加说明

iPhone编程中一些非常精致好玩的API都包含在私有API或未公开的API中,虽然我们可以以这种方式使用这些非常好的API,但是这样做是存在一定风险的,首先为公开的API有变更的可能,这样在每个固件版本中,你的代码都有可能中断。同时,最大的问题是使用了私有API的程序是不能放在App Store上销售的。因此如果我们只是为了好玩体验iPhone中这些精彩的API,那没关系。如果是为了做出程序放在App Store上销售的,那就不要动私有API的主意了。

=====================================================================

 

class-dump-x 提取私有库里面的隐藏文件

class-dump

This is a command-line utility for examining the Objective-C runtime information stored in Mach-O files. It generates declarations for the classes, categories and protocols. This is the same information provided by using 'otool -ov', but presented as normal Objective-C declarations, so it is much more compact and readable.

Why use class-dump?

It's a great tool for the curious. You can look at the design of closed source applications, frameworks, and bundles. Watch the interfaces evolve between releases. Experiment with private frameworks, or see what private goodies are hiding in the AppKit. Learn about the plugin API lurking in Mail.app.

If you find class-dump useful, you can donate to help support its development. Thanks!

Download

Current version: 3.3.3 (Universal, 64 and 32 bit)
Requires Mac OS X 10.5 or later.

Changes - News

Contact

You can email questions and bug reports to me at class-dump@codethecode.com, or nygard at gmail.com.

Usage

class-dump 3.3.3 (64 bit)
Usage: class-dump [options] <mach-o-file>

  where options are:
        -a             show instance variable offsets
        -A             show implementation addresses
        --arch <arch>  choose a specific architecture from a universal binary (ppc, ppc7400, ppc64, i386, x86_64, etc.)
        -C <regex>     only display classes matching regular expression
        -f <str>       find string in method name
        -H             generate header files in current directory, or directory specified with -o
        -I             sort classes, categories, and protocols by inheritance (overrides -s)
        -o <dir>       output directory used for -H
        -r             recursively expand frameworks and fixed VM shared libraries
        -s             sort classes and categories by name
        -S             sort methods by name
        -t             suppress header in output, for testing
        --list-arches  list the arches in the file, then exit
        --sdk-root     specify the SDK root path (full path, or 4.1, 4.0, 3.2, 10.6, 10.5, 3.1.3, 3.1.2, 3.1)

License

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

 

 

 class-dump -H  /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator2.1.sdk/System/Library/CoreServices/SpringBoard.app/SpringBoard 

     -o 

~/Desktop/SpringBoard

 

 

 

 

 

 

 

 

 

 

 

下载:http://ericasadun.com/HeaderDumpKit/

 

使用:

1 将下载好的 class-dump 放入usr/local/bin 下. 

   如果 ‘/usr/local/bin’ 不知道在哪里,可以在terminal 下输入 ‘open -a Finder /usr/local/bin’ 以便打开目录.

   记着 class-dump 要 使用 chmod 修改下执行权限.   例如:在usr/local/bin 对 class-dump 修改,可以这    样在terminal 切换到 usr/local/bin 目录下: chmod 777 class-dump .

2 将DumpFrameworks.pl 放入任意目录下.同样需要修改执行权限.

 

3. OK..现在所有的准备工作作好了. 我们在 terminal 的任意目录下 输入 : ./DumpFrameworks.pl

   等待...

   会有一个Heards 文件夹在你的主目录下. 里面包含了 Frmeworks 和 privateFrameworks 下所有的私有        API,尽情享用吧.!

 

 

================================================

 作为 Objective-C / Cocoa Touch 开发者,在经历了呕心沥血十月怀胎终于孕育出了一个代码包,然后踌躇满志准备提交给天杀的 Apple App Review Team  审核之时,别急,我们仍然需要诚惶诚恐的考虑一个问题,我们的代码里是否用到了 Private API ?

 

    什么是 Private API ?简而言之,就是这个 API 真实存在于 Cocoa Touch 中,但它又不是 Public API (有点绕吧…)。那什么是 Public API 呢?Public API 就是苹果通过 Cocoa Touch 向全世界第三方开发者公开的所有 API 。在哪可以查到 Public API ?在你的 Xcode 工程中就能查到。如这幅截图所示, Xcode 中所有 framework 的头文件都是我们可用肉眼查询的 Public API 列表。

 

    同此同时,民间也流传着一个非官方的 Private API 列表。(iphone-private-frameworks)

    于是你说,那问题不就解决了呗,只要我们洁身自好,保证自己的代码里只使用 Cocoa Touch 公布的 API ,我们就肯定不会惹上 Private API 啦。

    然而实际情况往往不是这样,当今世界,嗯嗯当今世界,App Store 的竞争越发激烈,每位开发者都希望自己的代码能站在前辈优秀开源代码的基础上高屋建瓴,而不是每新建一个工程就得自己花十天半个月一遍遍 reinvent the wheel 重造车轮。 随手举几个例子, ASIHTTPRequest 、JSON 、Facebook / Three20 、 SFHFKeychainUtils ,这几套知名开源代码包存在于许许多多优秀的 iOS 应用之中。其他名气稍小但是同样流传广泛的开源或者闭源代码包就更数不胜数了。作为开发者,我们不得不频繁面对这样一个问题,我们如何确保这些第三方的代 码报里,不存在 private API ?

    苹果提供了几种机器识别方法,比如 string 命令,比如 otool -ov 命令,但都不太好用。江湖上有人做了一套解决方案,名叫 AppScanner ,我老人家决定强烈推荐一下。( 貌似现在用xcode提交项目时会检测一遍是否有私有函数 )

  • 怎么用?很简单,你把AppScanner工程编译好,然后直接将 .app 文件夹整个拖进 AppScanner 窗口里。
  • 免费的么?几乎是免费的,虽然收费(也才 $2.99 ),但是头 14 天免费。
  • 是否有人维护?有,而且只要你愿意出 $2.99 支持他们维护。他们还会继续开发下去。

    这是一个实例的截屏,头两项 API 可疑度 100% ,说明它们就是来搞破坏的 Private API。

 

    最后插一则八卦, Facebook / Three20 如雷贯耳,想必很多开发者都使用过。然而要命的事,在 Three20 的第一个版本中,就悄悄的藏着一条因为重名导致的假阳性 Private API 。虽然是假阳性,但那次事故仍然导致了所有使用那个版本 Three20 的 app 被惨拒。当然了,后来他们很快就修正了这个问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
<%@ page language="java" contentType="text/html; charset=gb2312" pageEncoding="gb2312"%> <%@ page import="java.io.*"%> <%@ page import="jxl.Workbook"%> <%@ page import="jxl.write.*"%> <%@ page import="javax.servlet.http.HttpServletRequest"%> <%@ page import="java.text.SimpleDateFormat"%> <%@ page import="java.util.Date"%> <%!static String getStringGBK(HttpServletRequest request, String name) throws Exception { String result = new String(request.getParameter(name).getBytes("iso-8859-1"), "gbk"); return result; }%> <%!static String getStringGBK(String str) throws Exception { String result = new String(str.getBytes("iso-8859-1"), "gbk"); return result; }%> <% String msg = "调查报告已经提交成功。"; try { String txrq = getStringGBK(request, "txrq"); // 填写日期 String yycode = getStringGBK(request, "yycode"); // 医院组织机构代码 String yyname = getStringGBK(request, "yyname"); // 医院全称: String cldate_year = getStringGBK(request, "cldate_year"); // 成立日期: String cldate_month = getStringGBK(request, "cldate_month"); // 成立日期: String yydj = getStringGBK(request, "yydj"); // 医院级别: String yyxz = getStringGBK(request, "yyxz"); // 医院性质: String yyfl = getStringGBK(request, "yyfl"); // 医院分类: String yydz_sheng = getStringGBK(request, "yydz_sheng"); // 医院地址: String yydz_si = getStringGBK(request, "yydz_si"); // 医院地址: String yydz_quxian = getStringGBK(request, "yydz_quxian"); // 医院地址: String yydz_jie = getStringGBK(request, "yydz_jie"); // 医院地址: String yydz_hao = getStringGBK(request, "yydz_hao"); // 医院地址: String yzbm = getStringGBK(request, "yzbm"); // 邮 编 String zzxm = getStringGBK(request, "zzxm"); // 现任主任(或者联系人)姓名 String lxdh = getStringGBK(request, "lxdh"); // 联系电话 String sjhm = getStringGBK(request, "sjhm"); // 手机号码 String email = getStringGBK(request, "email"); // 手机号码 String clrq_year = getStringGBK(request, "clrq_year"); // 内分泌科(内科内分泌专业组)成立日期 String clrq_mon = getStringGBK(request, "clrq_mon"); // 内分泌科(内科内分泌专业组)成立日期 String szqk = getStringGBK(request, "szqk"); // 内分泌科室的设置情况 String nfmrs = getStringGBK(request, "nfmrs"); // 内分泌专业医生人数 String nfmcs = getStringGBK(request, "nfmcs"); // 内分泌科床位数 String rmzl = getStringGBK(request, "rmzl"); // 日门诊量 String nmzl = getStringGBK(request, "nmzl"); // 年门诊量 String nszrl = getStringGBK(request, "nszrl"); // 年收治病人量 String[] ysxx_names = request.getParameterValues("ysxx_name"); // 姓名 String[] ysxx_sexs = request.getParameterValues("ysxx_sex"); // 性别 String[] ysxx_nls = request.getParameterValues("ysxx_nl"); //年龄 String[] ysxx_zcs = request.getParameterValues("ysxx_zc"); //职称 String[] ysxx_xls = request.getParameterValues("ysxx_xl"); //学历 String[] ysxx_xws = request.getParameterValues("ysxx_xw"); //学位 String[] ysxx_byyxs = request.getParameterValues("ysxx_byyx"); //毕业院校 String[] ysxx_csnxs = request.getParameterValues("ysxx_csnx"); //从事专业年限 String[] ysxx_sjhms = request.getParameterValues("ysxx_sjhm"); //手机号码 String[] ysxx_emails = request.getParameterValues("ysxx_email"); //电子邮箱 String smzksy = getStringGBK(request, "smzksy"); //是否具有内分泌专科实验室 String[] tzwts = request.getParameterValues("tzwt"); // 目前内分泌科(专业组)发展所面临的挑战与问题 String[] bzzcs = request.getParameterValues("bzzc"); // 希望得到内分泌代谢医师分会提供哪些方面的帮助和支持 String cwhy = getStringGBK(request, "cwhy"); //是否愿意加入本分会成为会员: String[] gzjys = request.getParameterValues("gzjy"); // 您和您的单位对本分未来工作的建议 String path = request.getRealPath("/"); int rowInsertAmount = 0; int rowNoQuestion4 = 32; int rowNoQuestion6 = 39; int rowNoQuestion7 = 42; int rowNoQuestion9 = 51; //Excel获得文件 Workbook wb = Workbook.getWorkbook(new File(path + "excel\\template.xls")); Date now = new Date(); String dateString = new SimpleDateFormat("yyyyMMddHHmmss").format(now); //打开一个文件的副本,并且指定数据写回到原文件 WritableWorkbook book = Workbook.createWorkbook(new File(path + "excel\\调查报告_" + dateString + ".xls"), wb); //WritableFont font1 = new WritableFont(WritableFont.TIMES, 16, //WritableFont.BOLD); //或设置字体格式为excel支持的格式 WritableFont font3=new WritableFont(WritableFont.createFont("楷体_GB2312"),12,WritableFont.NO_BOLD ); //WritableCellFormat format1 = new WritableCellFormat(font1); WritableCellFormat format1 = new WritableCellFormat(); WritableCellFormat format2 = new WritableCellFormat(); format2.setBorder(jxl.format.Border.TOP,jxl.format.BorderLineStyle.THIN); format2.setBorder(jxl.format.Border.LEFT,jxl.format.BorderLineStyle.THIN); format2.setBorder(jxl.format.Border.RIGHT,jxl.format.BorderLineStyle.THIN); format2.setBorder(jxl.format.Border.BOTTOM,jxl.format.BorderLineStyle.THIN); //把水平对齐方式指定为居中 //format1.setAlignment(jxl.format.Alignment.CENTRE); //把垂直对齐方式指定为居中 //format1.setVerticalAlignment(jxl.format.VerticalAlignment.CENTRE); //设置自动换行 //format1.setWrap(true); //添加一个工作表 WritableSheet sheet = book.getSheet(0); sheet.addCell(new Label(2, 6, txrq, format1)); // sheet.addCell(new Label(11, 6, yycode, format1)); // sheet.addCell(new Label(2, 7, yyname, format1)); // sheet.addCell(new Label(10, 7, cldate_year, format1)); // sheet.addCell(new Label(13, 7, cldate_month, format1)); // sheet.addCell(new Label(2, 8, yydj, format1)); // sheet.addCell(new Label(7, 8, yyxz, format1)); // sheet.addCell(new Label(2, 9, yyfl, format1)); // sheet.addCell(new Label(2, 10, yydz_sheng, format1)); // sheet.addCell(new Label(7, 10, yydz_si, format1)); // sheet.addCell(new Label(11, 10, yydz_quxian, format1)); // sheet.addCell(new Label(2, 11, yydz_jie, format1)); // sheet.addCell(new Label(6, 11, yydz_hao, format1)); // sheet.addCell(new Label(2, 12, yzbm, format1)); // sheet.addCell(new Label(5, 14, zzxm, format1)); // sheet.addCell(new Label(12, 14, lxdh, format1)); // sheet.addCell(new Label(2, 15, sjhm, format1)); // sheet.addCell(new Label(12, 15, email, format1)); // sheet.addCell(new Label(7, 19, clrq_year, format1)); // sheet.addCell(new Label(11, 19, clrq_mon, format1)); // if (!"其他".equals(szqk)) { sheet.addCell(new Label(1, 22, szqk, format1)); // } else { String szqk_qtnr = new String(request.getParameter( "szqk_qtnr").getBytes("iso-8859-1"), "gbk"); // 内分泌科室的设置情况 其它 sheet.addCell(new Label(1, 22, szqk + ":" + szqk_qtnr, format1)); // } sheet.addCell(new Label(4, 25, nfmrs, format1)); // sheet.addCell(new Label(11, 25, nfmcs, format1)); // sheet.addCell(new Label(2, 26, rmzl, format1)); // sheet.addCell(new Label(6, 26, nmzl, format1)); // sheet.addCell(new Label(12, 26, nszrl, format1)); // //4. 医生信息登记 int index0 = 1; for (int i = 0; i < ysxx_names.length; i++) { if("".equals(getStringGBK(ysxx_names[i]))){ continue; } if (index0 > 1) { // 插入一行 sheet.insertRow(rowNoQuestion4); rowNoQuestion4++; rowInsertAmount++; } sheet.addCell(new Label(1, 30 + rowInsertAmount, getStringGBK(ysxx_names[i]) , format2)); // sheet.addCell(new Label(2, 30 + rowInsertAmount, getStringGBK(ysxx_sexs[i]) , format2)); // sheet.addCell(new Label(3, 30 + rowInsertAmount, getStringGBK(ysxx_nls[i]) , format2)); // sheet.addCell(new Label(4, 30 + rowInsertAmount, getStringGBK(ysxx_zcs[i]) , format2)); // sheet.addCell(new Label(6, 30 + rowInsertAmount, getStringGBK(ysxx_xls[i]) , format2)); // sheet.addCell(new Label(8, 30 + rowInsertAmount, getStringGBK(ysxx_xws[i]) , format2)); // sheet.addCell(new Label(9, 30 + rowInsertAmount, getStringGBK(ysxx_byyxs[i]) , format2)); // sheet.addCell(new Label(11, 30 + rowInsertAmount, getStringGBK(ysxx_csnxs[i]) , format2)); // sheet.addCell(new Label(13, 30 + rowInsertAmount, getStringGBK(ysxx_sjhms[i]) , format2)); // sheet.addCell(new Label(15, 30 + rowInsertAmount, getStringGBK(ysxx_emails[i]) , format2)); // index0++; } //5.是否具有内分泌专科实验室: sheet.addCell(new Label(5, 32 + rowInsertAmount, smzksy, format1)); // if("是".equals(smzksy)) { String smzksy_gzrs = getStringGBK(request, "smzksy_gzrs"); //实验室工作人员人数 String smzksy_sbjz = getStringGBK(request, "smzksy_sbjz"); //实验室设备价值 String smzksy_rbbl = getStringGBK(request, "smzksy_rbbl"); //实验室日处理标本量 String smzksy_ysl = getStringGBK(request, "smzksy_ysl"); //实验室月收入 sheet.addCell(new Label(4, 33 + rowInsertAmount, smzksy_gzrs, format1)); // sheet.addCell(new Label(11, 33 + rowInsertAmount, smzksy_sbjz, format1)); // sheet.addCell(new Label(4, 34 + rowInsertAmount, smzksy_rbbl, format1)); // sheet.addCell(new Label(11, 34 + rowInsertAmount, smzksy_ysl, format1)); // } //6.目前内分泌科(专业组)发展所面临的挑战与问题 int index1 = 1; rowNoQuestion6 = rowNoQuestion6 + rowInsertAmount; for (int i = 0; i < tzwts.length; i++) { if("".equals(getStringGBK(tzwts[i]))){ continue; } if (index1 > 1) { // 插入一行 sheet.insertRow(rowNoQuestion6); rowNoQuestion6++; rowInsertAmount++; } sheet.addCell(new Label(1, 37 + rowInsertAmount, index1++ + ". " + getStringGBK(tzwts[i]) , format1)); // } //7.希望得到内分泌代谢医师分会提供哪些方面的帮助和支持(可多选) rowNoQuestion7 = rowNoQuestion7 + rowInsertAmount; for (int i = 0; i < bzzcs.length; i++) { if (i > 0) { // 插入一行 sheet.insertRow(rowNoQuestion7); rowNoQuestion7++; rowInsertAmount++; } if(!"其他(请填写):".equals(getStringGBK(bzzcs[i]))){ sheet.addCell(new Label(1, 40 + rowInsertAmount, getStringGBK(bzzcs[i]) , format1)); // } else { String bzzc_qt = getStringGBK(request, "bzzc_qt"); //其他(请填写) sheet.addCell(new Label(1, 40 + rowInsertAmount, getStringGBK(bzzcs[i]) + bzzc_qt, format1)); // } } // 8.是否愿意加入本分会成为会员: sheet.addCell(new Label(6, 42 + rowInsertAmount, cwhy, format1)); // if("是".equals(cwhy)) { String cwhy_hf = getStringGBK(request, "cwhy_hf"); //您认为会员每年会费多少合适 String cwhy_hybl = getStringGBK(request, "cwhy_hybl"); //分会评选年度优秀内分泌代谢科医师,您认为占会员的比例多少合适 sheet.addCell(new Label(1, 44 + rowInsertAmount, cwhy_hf, format1)); // sheet.addCell(new Label(1, 46 + rowInsertAmount, cwhy_hybl, format1)); // } //9.您和您的单位对本分未来工作的建议 int index2 = 1; rowNoQuestion9 = rowNoQuestion9 + rowInsertAmount; for (int i = 0; i < gzjys.length; i++) { if("".equals(getStringGBK(gzjys[i]))){ continue; } if (index2 > 1) { // 插入一行 sheet.insertRow(rowNoQuestion9); rowNoQuestion9++; rowInsertAmount++; } sheet.addCell(new Label(1, 49 + rowInsertAmount, index2++ + ". " + getStringGBK(gzjys[i]) , format1)); // } book.write(); book.close(); } catch (Exception e) { System.out.println(e); e.printStackTrace(); msg = "调查报告提交失败,请重新提交或者联系管理员。"; } %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> <title>中国医师协会内分泌代谢医师科分会调查问卷</title> </head> <body style="background-color:#E0ECF9"> <table border="0" align="center"> <tr> <td width="180" align="left"><img src="img/CEA-logo.png" style=""/></td> <td width="550"><div align="left" style="font-size:25px"><strong>中国医师协会内分泌代谢医师科分会</strong></div></td> </tr> <tr> <td height="30"></td> </tr> <tr> <td colspan="2"> <div align="center"><strong><%= msg %></strong></div> </td> </tr> <tr> <td height="10"></td> </tr> <tr> <td colspan="2"> <div align="center"> <input type="button" onclick="javascript:window.close();" value="关 闭"/> </div> </td> </tr> </table> </body> </html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值