底层强行调用高层接口

奇技淫巧 指过于奇巧而无益的技艺与制品.

先来看一段代码

// A.h- (void)funa{[b funB];} // b.h-(void)funB{// 我在这里如何得到a呢}

有的时候底层就是想知道高层,别纠结什么时候,这个主题下的文章注定都是这个德行的.我们又不想把a传给b.那么有办法的到a么,答案肯定是有的. 方法在调用的过程中呢,会有个压栈的过程,oc下栈里的东西按照高位到地位排序为: 1 self对象 2 方法sel 3 参数… 4变量… 在方法funb构造一个变量,然后地址 加加 就获得了方法funB了,再 加加 就获得b对象了

-(void)funB{int a = 999;int *obj = &a + 2;SEL *sel = &a + 1;NSLog(@”%s, a %p”, __FUNCTION__, &a);NSLog(@”%s, obj %p”, __FUNCTION__, obj);NSLog(@”%s, sel %p”, __FUNCTION__, sel);NSLog(@”%@”, *obj);NSString *str2 = NSStringFromSelector(*sel);NSLog(@”%@”, str2);}

这个时候如果我们在–会发生什么事情呢?当我们在 加加加 的时候,我们就进入到方法funa用到的栈的地址了,我们可以得到funa里的局部变量,这种情况下再 加加 就可以得到a了.整理下思路就是: 1 获取堆栈信息 2 将funa当作锚点 3 funa的地址 加加 就是对象a

// a.h-(void)funA{NSLog(@”%s”, __FUNCTION__);}- (IBAction)click2:(id)sender {[_test funB];}// b.h-(void)funB{int a = 999;id b = @”bbbb”;NSString *name = [CallStack preSelName];// NSLog(@”%@”, name);NSString *clazz = [CallStack preSelName];// NSLog(@”%@”, clazz);SEL *preSel = &a + 1;int i = 0;SEL *sel = &a + 1;NSString *str2 = NSStringFromSelector(*sel);NSString *selName = NSStringFromSelector(*preSel);while (![name isEqualToString:selName]){i++;preSel = &a + i;selName = NSStringFromSelector(*preSel);if (selName){// NSLog(@”preSel: %p %@”, *preSel, selName);}}// NSLog(@”%@”, selName);int *preClazz = *(preSel + 1);// NSLog(@”%@”, preClazz);id objc= (__bridge id)((void *)(preClazz));NSLog(@”%@”, objc);[objc performSelector:@selector(funA) withObject:nil];}

运行的结果是 2015-03-24 21:13:51.629 testaddress[12616:2623719] -[FirstViewController funA] 底层的b在不知道高层a的情况下,调用a的方法funA.

demo请看 https://github.com/uxyheaven/demo_testaddress 里的Button2

,爬上那座山,听最圣洁的经。

底层强行调用高层接口

相关文章:

你感兴趣的文章:

标签云: