runtime的確是很神奇的東西载佳,可以做到很多我們本來做不到的事情,系統(tǒng)的UIWebview就有很多很有用的接口方咆,拿到它,我們就能做到跟蘋果的Safari一樣的體驗(yàn)褪储,下面我就講一講利用runtime如何調(diào)用私有API
//新建一個(gè)Person類 .h 文件如下
#import <Foundation/Foundation>
@interface Person : NSObject
@end
//.m 文件如下
#import "Person.h"
@implementation Person
- (void)eat {
NSLog(@"eat");
}
@end
在其他文件如何調(diào)用eat 方法
Person*person = [[Personalloc]init];
SELtheSEL =nil;
MyIMPtheIMP =nil;
[NSObject test:@"eat"theClass:[personclass]value1:&theSELvalue2:&theIMPvalue3:nil];
theIMP(person,theSEL);
運(yùn)行代碼神奇的發(fā)現(xiàn)了打印 MethodSwizzle[78072:7164695] eat
那么+(BOOL)test:(NSString)name theClass:(Class)theClass value1:(SEL)value1 value2:(IMP)value2 value3:(Method)value3卵渴;這個(gè)方法是如何實(shí)現(xiàn)的,當(dāng)然是利用runtime可以動(dòng)態(tài)獲取方法列表的特點(diǎn)
@try{
unsigned int methodCount;
Method* methods =class_copyMethodList(theClass, &methodCount);
if(!methods)
{ returnNO; }
for(inti =0; i < methodCount; i++)
{
Methodmethod = methods[i];
p_my_structmethodStruct = (p_my_struct)method;
constchar* methodName = (constchar*)(sel_getName(methodStruct->name));
if(methodName)
{
const char* theName = [name cStringUsingEncoding:NSUTF8StringEncoding];
if(strcmp(theName, methodName) ==0)
{
if(value1)
{
*value1 = methodStruct->name;
}
if(value2)
{
*value2 = methodStruct->imp;
}
if(value3)
{
*value3 = method;
}
free(methods);
returnYES;
}
}
}
free(methods);
returnNO;
}@catch(NSException *e) {
NSLog(@"Call %@ failed with error:%@", name, e);
if(value1)
{
*value1 =NULL;
}
if(value2)
{
*value2 =NULL;
}
if(value3)
{
*value3 =NULL;
}
returnNO;
}
這段代碼的意思就是獲取這個(gè)類的所有方法鲤竹,找出這個(gè)方法對(duì)應(yīng)的名字浪读,與給出的名字比較,如果相同辛藻,返回IMP指針和SEL指針碘橘,拿到了這兩個(gè)東西就可以調(diào)用我們的私有方法了,當(dāng)然如果調(diào)用的是系統(tǒng)的私有api揩尸,這個(gè)api必須先做成加密字符串蛹屿,用的時(shí)候解密即可屁奏。
runtime還可以做到很多事情岩榆,方法交換,原理很簡(jiǎn)單坟瓢,這里就不細(xì)講勇边,直接給出demo