iOS 调用私有方法的问题

问题:已知ClassA,有一个私有方法test,通过映射的方式,调用私有方法test。
我的观点
写这个问题答案之前,我想说的是,我的逻辑思维中,直觉还是不灵敏,好多事情,都想当然了,我觉得思维缜密,直觉很重要,这个是天赋,还有就是习惯。
像我这样直觉不灵敏的,遇见问题,一定要仔细想想,是否有考虑不周的地方,这个要养成这样的习惯。
另一种观点
另外跟大洋洋讨论这个题的时候,又衍生出来了另一个问题,我觉得也应该记录下来,好好琢磨琢磨。因为讨论这个问题的时候,他也没有答完整,他总结说:“1. 现在回答这类问题,总感觉答不上,2. 感觉iOS会啥技术,也说不出来啥体系,感觉自己的知识体系树没有建立起来,就是遇见问题解决问题。” 我也有这样的情况,我觉得我以前的开发,就是遇见问题,解决问题,再遇见问题,在解决问题,得过且过,后来又有了改变,开始注重整体的结构代码机构,开始喜欢学习设计模式,学习技巧,因为这些经验可以有效的避免一些问题的发生,让代码变得更加优雅,好维护好修改,其实还是遇见问题解决问题。

解决这个问题
解决这个问题,要注意的几个点:ClassA ,私有方法test映射调用私有方法

刚开始的想法是:
ClassA 这个类的权限问题,是否能够引用,如果是public的,可以引用可以直接new对象,如果是private或者是protect,引用不了就可以通过NSClassFromString来获得这个ClassA的类型来进行处理。
私有方法我想简单了,这里我开始并没有考虑到test是否有参数和返回值的问题
映射就是通过类名找到类的类型,为后续初始化提供准备
调用私有方法,msg_send方法,或者performForSelector方法。

#import "A.h"

@implementation A

- (void)test {
    NSLog(@"可以调用私有方法");
}

@end

    A * a = [[A alloc] init];
//    [a performSelector:NSSelectorFromString(@"test")];
    [a performSelector:@selector(test)];

image.png

从上面打印结果可以看出,通过performSelector方法是可以调用test私有方法的,但是会有警告。
带有参数甚至是多个参数的

#import "A.h"

@implementation A

- (void)test:(NSString *)c1 {
    NSLog(@"可以调用私有方法%@",c1);
}

@end
  A * a = [[A alloc] init];
  [a performSelector:@selector(test:) withObject:@"加了一个参数"];

image.png

这个思路有个问题不好解决
test这个方法,没参数,有参数,有多个参数,通过performSelector这个api,没法做出抽象,只能通过判断这几种情况,去硬处理。

从performSelector的这几个api的设计来看,猜测运行时的objc_msgSend方法应该会有对这几个perfomeSelector方法的抽象。

既然用运行时,那么就先用运行时的方法,检查是否有参数的问题。
这个地方我在做的时候,有点卡顿,卡顿的原因是想通过运行时的方法,通过方法名找到方法,再监测这个方法里面有没有参数,有参数参数的类型是什么样的。但是发现运行时的方法,并没有提供我这个思路的api。

这个地方需要换一个思路,私有方法是不公开的,test这个私有方法是怎么得到的,一种情况是能看到源文件,也就是.m文件是可以看到的,所以可以直接确定是否有返回值,是否有参数。另一种情况是看不到.m文件,看不到文件的,就需要通过运行时方法,打印这个类中的所有方法,然后找到想要用的方法,打印的时候,也是可以把方法的参数,返回值类型打印出来的。
所以说,test这个方法是人为选择出来的,也就是说我们要调用这个方法的时候,会明确知道这个方法是不是有返回值,是不是有参数,有几个参数等等信息。
假设有5个参数的时候怎么调用

#import "A.h"

@implementation A
- (void)test:(NSString *)c1 c2:(NSString *)c2 c3:(NSString *)c3 c4:(NSString *)c4 c5:(NSString *)c5 {
    NSLog(@"私有方法含有多个参数%@,%@,%@,%@,%@",c1,c2,c3,c4,c5);
}
@end
//调用代码
 Class  A = NSClassFromString(@"A");
    id  a = [[A alloc] init];
    ((void (*)(id,SEL,id,id,id,id,id))objc_msgSend)(a,@selector(test:c2:c3:c4:c5:),@"1",@"2",@"3",@"4",@"5");

输出结果


image.png

如果有返回值的怎么调用

#import "A.h"

@implementation A
- (NSString *)test:(NSString *)c1 c2:(NSString *)c2 c3:(NSString *)c3 c4:(NSString *)c4 c5:(NSString *)c5 {
    return [NSString stringWithFormat:@"私有方法含有多个参数%@,%@,%@,%@,%@",c1,c2,c3,c4,c5];
}
@end
//调用代码
  Class  A = NSClassFromString(@"A");
  id  a = [[A alloc] init];
  NSString * b =  ((NSString * (*)(id,SEL,id,id,id,id,id))objc_msgSend)(a,@selector(test:c2:c3:c4:c5:),@"1",@"2",@"3",@"4",@"5");
  NSLog(@"%@",b);

输出结果


image.png

归纳总结
已知类名,调用私有方法,比较好的方法是

  1. 创建类的时候,用反射机制,得到类class, 然后实例化。
  2. 通过实例对象,调用私有方法的时候,要考虑私有方法是否有有返回值,是否有参数,根据不同的情况进行处理。

既然上面的方式可以成功,那也也可以直接用函数指针调用

#import "A.h"

@implementation A

- (void)test {
    NSLog(@"可以调用私有方法");
}
@end

//调用方法
    Class  A = NSClassFromString(@"A");
    id  a = [[A alloc] init];
    IMP imp = [a methodForSelector:@selector(test)];
    void  (* tempFunc)(id target, SEL) = (void *)imp;
    tempFunc(a, @selector(test));

只要能拿到私有方法的指针,就可以想办法通过指针去调用。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容