日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Runtime消息动态解析与转发流程

發布時間:2023/12/20 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Runtime消息动态解析与转发流程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

先上圖:

?

下面根據具體代碼看這張圖。

一、創建一個Person類,

?Person.h

#import <Foundation/Foundation.h>@interface Person : NSObject-(void)sendMessage:(NSString *)message;@end

Person.m

#import "Person.h" #import <objc/runtime.h>@implementation Person@end

大家可以看到,Person類只聲明了 sendMessage:方法,在.m文件里沒有實現這個方法。

?

這時,如果在viewController中調用Person類的sendMessage方法,程序會發生崩潰。

#import "ViewController.h" #import "Person.h"@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];[[[Person alloc]init] sendMessage:@"Hello"];}

?

?

結合上面的圖片,我們說說消息處理的機制。

1.當我們調用的方法沒有具體的實現時,會調用

+ (BOOL)resolveInstanceMethod:(SEL)sel;

+(BOOL)resolveInstanceMethod:(SEL)sel{NSString *methodName = NSStringFromSelector(sel);if ([methodName isEqualToString:@"sendMessage:"]) {//我們可以在這里添加方法的實現return class_addMethod(self, sel, (IMP)sendMessage, "v@:@");}return NO;}void sendMessage (id self, SEL _cmd, NSString *message){NSLog(@"message=%@",message); }

BOOL class_addMethod(Class cls, SEL name, IMP imp,?const char *types):為類動態添加方法。如果有同名會返回NO,成功返回YES。

其中的參數types查詢地址:(v:表示void, @:表示類型,等等)

?

2. 如果?resolveInstanceMethod:方法返回NO,調用

-(id)forwardingTargetForSelector:(SEL)aSelector;

這個方法是找備用者,比如:Animal類。

Animal.h

#import <Foundation/Foundation.h>@interface Animal : NSObject@end

Animal.m

#import "Animal.h"@implementation Animal-(void)sendMessage:(NSString *)message{NSLog(@"message=%@",message); }@end

Animal類沒有聲明sendMessage:方法,但在.m文件里有這個方法的實現,可以作為備用者。如下:

-(id)forwardingTargetForSelector:(SEL)aSelector{NSString *methodName = NSStringFromSelector(aSelector);if ([methodName isEqualToString:@"sendMessage:"]) {if ([[Animal new] respondsToSelector:aSelector]) {return [Animal new];}}return [super forwardingTargetForSelector:aSelector]; }

3. 如果?forwardingTargetForSelector:(SEL)aSelector返回 nil。

// 若前兩種方法都不處理,則走這里 // 1)方法簽名 -(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{NSString *methodName = NSStringFromSelector(aSelector);if ([methodName isEqualToString:@"sendMessage:"]) {return [NSMethodSignature signatureWithObjCTypes:"v@:@"];}return [super methodSignatureForSelector:aSelector]; } // 2) 簽名后,消息轉發,找備用者 -(void)forwardInvocation:(NSInvocation *)anInvocation{SEL selector = [anInvocation selector];Animal *animal = [Animal new];if ([animal respondsToSelector:selector]) {[anInvocation invokeWithTarget:animal];} else{[super forwardInvocation:anInvocation];} }

?

4.如果走到第3步,仍然不做處理,如下:

-(void)forwardInvocation:(NSInvocation *)anInvocation{[super forwardInvocation:anInvocation]; }

這時為了程序的健壯性,防止崩潰,可以用以下方法處理。

// 若前3方法都不處理,為了防止崩潰,可調用此方法 -(void)doesNotRecognizeSelector:(SEL)aSelector{NSString *methodName = NSStringFromSelector(aSelector);NSLog(@"找不到 %@ 這個方法的實現",methodName); }

?

附加源碼

轉載于:https://www.cnblogs.com/lfyDragon/p/9177710.html

總結

以上是生活随笔為你收集整理的Runtime消息动态解析与转发流程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。