当前位置:网站首页>Message forwarding mechanism -- save your program from crashing
Message forwarding mechanism -- save your program from crashing
2022-07-28 05:05:00 【Lu_ Ca】
Preface :
I have always known iOS Message forwarding mechanism in , I haven't summarized . This article is a summary of previous fragment knowledge . Mainly related to runtime Message passing and methods if no object is found , The system provides us with three rescue opportunities . I don't say much nonsense , Direct text .
Runtime Messaging for
We all know OC It's a dynamic language .OC Language is not directly recognized by computers . I need to convert to C Language , And then into assembly language , Finally, it turns into machine language recognized by computer .
When we call an object's method [objc foo] when , The compiler will convert the code into message sending objc_msgSend(objc foo). The specific implementation process is like this :
- First , The system goes through objc Of isa The pointer finds its corresponding class.
- then , stay class Of method list Search method in the list of foo.
- If no corresponding method is found , Just look in its parent class .
- Find the corresponding method in this process , Just go through the method IMP The pointer ( Method address pointer ) Execution method .
Of course, sometimes we have no implementation method foo. For example, we call an immutable string modification method . Actually , The modification method is only implemented in the variable string class . Then the program will crash , Error message unrecognized selector. This method cannot be recognized . In fact, before this collapse , The system provides us with three opportunities to save , This is the message forwarding process .
forward
When the system cannot find the method you want to execute , Will provide three opportunities to save your program from crashing .
1、 Dynamic method analysis
oc At run time , Object method calls execute +resolveInstanceMethod: Class method calls will execute +resolveClassMethod: Method , In this way, we can , Perform a process . adopt runtime Dynamic adding method , And forward the message to the alternate receiving method .

You can see , I didn't realize foo: Method , But the running program did not crash , And implemented my new definition newFooMethod Method .
then , If we don't deal with this step accordingly , The program will proceed to the second step , Find the implementation object of the message .
2、 Define alternate recipients
If the first step , No rescue , Then the program will go to this step , The system will call - (id)forwardingTargetForSelector:(SEL)aSelector Method . Give you a chance to pass messages to other objects . therefore , If you want to save in this step . We need to define an alternate class , To process messages target. As long as we implement this method in our spare class , Then the system will execute this method .
#import <objc/runtime.h>
@interface OtherPerson : NSObject
@end
@implementation OtherPerson
// Definition foo Method , Handle the forwarded foo Method
- (void)foo {
NSLog(@"Person foo func");
}
@end
@implementation TestViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self performSelector:@selector(foo)];
// Do any additional setup after loading the view.
}
void newFooMethod(){
NSLog(@"Now I am new foo func.");
}
+ (BOOL)resolveInstanceMethod:(SEL)sel{
// if(sel == @selector(foo)){
// class_addMethod([self class], sel, (IMP)newFooMethod, "[email protected]:");
// return YES;
// }
// Directly execute the system method , Don't take the above adding method , If you can't find it, you'll go down and forward
return [super resolveInstanceMethod:sel];
}
- (id)forwardingTargetForSelector:(SEL)aSelector{
if(aSelector == @selector(foo)){
return [OtherPerson new];// Set forwarded target processing method
}
return [super forwardingTargetForSelector:aSelector];
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
@end
Then run the code , I found it printed Person foo func. There was no collapse , explain foo Method has been forwarded to OtherPerson Class to execute .
3、 Full message forwarding
If the first two methods fail to save , Then the message forwarding goes to the last step . If the message cannot be processed at this step , that Runtime Will send out -doesNotRecognizeSelector: news , The program then hangs up .
Here we need a higher price to save , We need to get the method signature first . Pass the method signature to the system
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector Method . When this method receives the method signature ,runtime It creates a NSInvocation object , send out - (void)forwardInvocation:(NSInvocation *)anInvocation To the target .
#import <objc/runtime.h>
@interface OtherPerson : NSObject
@end
@implementation OtherPerson
- (void)foo {
NSLog(@"Person foo func");
}
@end
@interface TestViewController ()
@end
@implementation TestViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor yellowColor];
[self performSelector:@selector(foo)];
// Do any additional setup after loading the view.
}
void newFooMethod(){
NSLog(@"Now I am new foo func.");
}
+ (BOOL)resolveInstanceMethod:(SEL)sel{
// if(sel == @selector(foo)){
class_addMethod([self class], sel, (IMP)newFooMethod, "[email protected]:");
// return NO;
// }
// Take a systematic approach , Method not found , Take the second step
return [super resolveInstanceMethod:sel];
}
- (id)forwardingTargetForSelector:(SEL)aSelector{
// if(aSelector == @selector(foo)){
// return [OtherPerson new];
// }
// The method of executing the system , Because there is no response class , So it will enter the third step , That's the method below
return [super forwardingTargetForSelector:aSelector];
}
// This is the last step to save the collapse
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
if([NSStringFromSelector(aSelector) isEqualToString:@"foo"]){
// Method selector
SEL fooSEL = @selector(foo);
// Method signature
NSMethodSignature *fooSignature = [NSString methodSignatureForSelector:fooSEL];
// Returns a method signature
return fooSignature;
}
return [super methodSignatureForSelector:aSelector];
}
// Forward by method signature
- (void)forwardInvocation:(NSInvocation *)anInvocation{
SEL sel = anInvocation.selector;
OtherPerson *person = [OtherPerson new];
if([person respondsToSelector:sel]){
[anInvocation invokeWithTarget:person];
}else{
// There is no way to respond
[self doesNotRecognizeSelector:sel];
}
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
@end
By running the program , Print the Person foo func, There was no program crash . thus , The message is forwarded three times and the rescue opportunity is over .
Next, let's talk about method signature
There are two ways to obtain method signatures , One is to manually generate method signatures , The other is to automatically generate method signatures .
Generate method signatures manually
Generate method signatures manually , You need to pass the return value of the method , Parameters and other information to generate signatures through methods . for example [NSMethodSignature signatureWithObjCTypes:"@@*"]
Here, the side parameter is an array of strings . This array contains the return value of the method 、 Parameter information . The first @ Indicates that the return value of the method is a id Object of type , And the second one. @ The representation method receives a id Parameters , final * The representation method receives a string (char*) Parameters of type . In fact, apple officially has a comparison table TypeEncoding
Automatic generation of method signature
In general , We generate method signatures automatically . That is, the form of the code above , Don't pass one c The string array of represents the return value parameter information of the method . It is also more accurate , There are two methods below , Can generate the signature of the method .
// Get the instance method signature from the class
fooSignature = [NSString instanceMethodSignatureForSelector:fooSEL];
// Get the class method signature from the class
fooSignature = [NSString methodSignatureForSelector:fooSEL];
边栏推荐
- Activation functions sigmoid, tanh, relu in convolutional neural networks
- UI automation test farewell from now on, manual download browser driver, recommended collection
- 多御安全浏览器将改进安全模式,让用户浏览更安全
- 【CVPR2022】Lite Vision Transformer with Enhanced Self-Attention
- HDU 1522 marriage is stable
- 【ARIXV2204】Neighborhood attention transformer
- Paper reading notes -- crop yield prediction using deep neural networks
- String 0123456789abcdef, what is the number of substrings (not empty and not the same string itself) [Hangzhou multi tester] [Hangzhou multi tester _ Wang Sir]
- HDU 3585 maximum shortest distance
- POJ 3417 network (lca+ differential on tree)
猜你喜欢

【ARXIV2205】EdgeViTs: Competing Light-weight CNNs on Mobile Devices with Vision Transformers

CPU and memory usage are too high. How to modify RTSP round robin detection parameters to reduce server consumption?

Dynamic SQL and paging

这种动态规划你见过吗——状态机动态规划之股票问题(中)

flink思维导图

RT_ Use of thread message queue

Visual studio 2019 new OpenGL project does not need to reconfigure the environment

MySQL(5)

【CVPR2022】Lite Vision Transformer with Enhanced Self-Attention
![[paper notes] - low illumination image enhancement - zeroshot - rrdnet Network - 2020-icme](/img/e3/f9c6bfdbcd5dffd406e3f1d2331050.png)
[paper notes] - low illumination image enhancement - zeroshot - rrdnet Network - 2020-icme
随机推荐
How to analyze fans' interests?
Handling of web page image loading errors
HDU 3078 network (lca+ sort)
(manual) [sqli labs27, 27a] error echo, Boolean blind injection, filtered injection
What should testers know about login security?
Analyze the emotional elements contained in intelligent sweeping robot
The difference between alter and confirm, prompt
为什么md5不可逆,却还可能被md5免费解密网站解密
What is the reason why the easycvr national standard protocol access equipment is online but the channel is not online?
Method of converting UI file to py file
Service object creation and use
How to quickly turn function test to automatic test
From the basic concept of micro services to core components - explain and analyze through an example
FPGA: use PWM wave to control LED brightness
[daily question 1] 735. Planetary collision
HDU 1435 stable match
FreeRTOS startup process, coding style and debugging method
HDU 1914 the stable marriage problem
Leetcode 18. sum of four numbers
Redux basic syntax