Objective-C Qiqiao technology-underlying forced calling of high-level interfaces, objective-c high-level
Technical lust refers to technologies and products that are too clever and useless.
Let's take a look at a piece of code.
//. H-(void) funa {[B funB];} // B. h-(void) funB {// How can I obtain object a of call object B here}
Sometimes the bottom layer is to know the top layer, so don't worry about when, the articles under this topic are doomed to be this virtue. we do not want to pass a to B. so there is a way to get to a, the answer is certainly there.
In the process of calling the method, there will be a stack pressure process. The items in the stack under oc are sorted as follows:
1 self object 2 method sel 3 parameter... 4 variables...
Construct a variable in the method funb, add the address and obtain the method funB, and then add the value to obtain the B object.
-(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);}
What will happen if we are in Canada at this time? When we are adding and adding, we will go to the stack address used by funa. We can get the local variable in funa, in this case, add a To Get. the thought is:
1. Obtain stack information
2. Use funa as the anchpoint
3. Add the funa address to object.
// 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); 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];}
The result is
21:13:51. 629 testaddress [12616: 2623719]-[FirstViewController funA]
The underlying B calls the method funA OF a without knowing the high-level.
See demo
Https://github.com/uxyheaven/demo_testaddress
In Button2