自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

iOS消息轉(zhuǎn)發(fā)機(jī)制Demo解析

移動(dòng)開發(fā)
假設(shè)說我們聲明一個(gè)類, 初始化對(duì)象, 并且在此類聲明一個(gè)方法, 調(diào)用方法的時(shí)候底層是怎么處理的呢? 今天我們來(lái)簡(jiǎn)單模擬測(cè)試, 來(lái)看道理發(fā)生了什么?

假設(shè)說我們聲明一個(gè)類, 初始化對(duì)象, 并且在此類聲明一個(gè)方法, 調(diào)用方法的時(shí)候底層是怎么處理的呢? 今天我們來(lái)簡(jiǎn)單模擬測(cè)試, 來(lái)看道理發(fā)生了什么

以下是調(diào)用方法處理的方案圖, 按照方案順序去處理 

以下是系統(tǒng)方法 

  1. //消息轉(zhuǎn)發(fā) 
  2. //- (id)forwardingTargetForSelector:(SEL)aSelector OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0); 
  3. //標(biāo)準(zhǔn)的消息轉(zhuǎn)發(fā) 
  4. //- (void)forwardInvocation:(NSInvocation *)anInvocation OBJC_SWIFT_UNAVAILABLE(""); 
  5. //- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector OBJC_SWIFT_UNAVAILABLE(""); 
  6. // 
  7. //動(dòng)態(tài)方法解析 
  8. //+ (BOOL)resolveClassMethod:(SEL)sel OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0); 
  9. //+ (BOOL)resolveInstanceMethod:(SEL)sel OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0); 

Demo解析

基礎(chǔ)步驟

創(chuàng)建類, Person類, 聲明方法, 并且在ViewController進(jìn)行初始化調(diào)用 

  1. VC中 
  2. Person *person = [Person new]; 
  3. [person run]; 
  4. Person類中 
  5. - (void)run;//沒有實(shí)現(xiàn) 

此時(shí)運(yùn)行是不是會(huì)報(bào)錯(cuò)呢? 就是這個(gè)常見的錯(cuò)誤

“ - [Person run]: unrecognized selector sent to instance 0x600000008310’ “

那么這樣做到底發(fā)生了什么? 做了哪些事情? 我們一步步來(lái)剖析

動(dòng)態(tài)測(cè)試

在Presenter類中, 寫動(dòng)態(tài)方法 

  1. + (BOOL)resolveInstanceMethod:(SEL)sel{ 
  2. NSLog(@"sel = %@",NSStringFromSelector(sel)); 
  3. return [super resolveInstanceMethod:sel]; 

再次運(yùn)行Demo就會(huì)走到這個(gè)方法中, 也就是我們所指的方案1, 此時(shí)打印出來(lái)的scl為” 消息轉(zhuǎn)發(fā)機(jī)制Demo[41829:4186268] sel = run “

解析模擬 

  1. + (BOOL)resolveInstanceMethod:(SEL)sel{ 
  2. NSLog(@"sel = %@",NSStringFromSelector(sel)); 
  3. //1.判斷沒有實(shí)現(xiàn)方法, 那么我們就是動(dòng)態(tài)添加一個(gè)方法 
  4. if (sel == @selector(run:)) { 
  5. class_addMethod(self, sel, (IMP)newRun, "v@:@:"); 
  6. return YES; 
  7. return [super resolveInstanceMethod:sel]; 

聲明函數(shù) 

  1. void newRun(id self,SEL sel,NSString *str) { 
  2. NSLog(@"---runok---%@",str); 

溫馨小提示, 動(dòng)態(tài)添加方法參數(shù)意譯 : //將要添加方法的類/sel名/IMP函數(shù)指針<添加函數(shù)>, 官方文檔其實(shí)是有解釋的

此時(shí)我們?cè)俅芜\(yùn)行, 那么打印結(jié)果就來(lái)了” 消息轉(zhuǎn)發(fā)機(jī)制Demo[43269:4212899] —runok—ok跑 “, 這樣的話我們就解決掉了報(bào)錯(cuò)這個(gè)問題

消息轉(zhuǎn)發(fā)重定向測(cè)試

此時(shí)我們新創(chuàng)建一個(gè)類Mbxb, 此時(shí)我們還是重新寫一個(gè)同名字的方法run方法, 并且進(jìn)行實(shí)現(xiàn) 

  1. - (void)run{ 
  2. NSLog(@"---Mbxbrunok---"); 

解析

此時(shí)有兩個(gè)同樣的方法, 我們重新在Person類中

來(lái)實(shí)現(xiàn)方法 

  1. - (id)forwardingTargetForSelector:(SEL)aSelector{ 
  2. NSLog(@"aSelector = %@",NSStringFromSelector(aSelector)); 
  3. return [super forwardingTargetForSelector:aSelector]; 

此時(shí)運(yùn)行測(cè)試, 動(dòng)態(tài)測(cè)試輸出” 消息轉(zhuǎn)發(fā)機(jī)制Demo[45875:4255869] sel = run “, 消息轉(zhuǎn)發(fā)重定向輸出” 消息轉(zhuǎn)發(fā)機(jī)制Demo[45875:4255869] —Mbxbrunok— “, 同樣也可以找見方法run

當(dāng)我們進(jìn)行處理 

  1. - (id)forwardingTargetForSelector:(SEL)aSelector{ 
  2. NSLog(@"aSelector = %@",NSStringFromSelector(aSelector)); 
  3. return [[Mbxb alloc]init]; 

那么此時(shí)運(yùn)行成功輸出, “ —Mbxbrunok— “

生成方法簽名轉(zhuǎn)發(fā)消息

此時(shí)我們?cè)赑erson類中, 生成方法簽名 

  1. - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector OBJC_SWIFT_UNAVAILABLE(""){ 
  2. //轉(zhuǎn)化字符 
  3. NSString *sel = NSStringFromSelector(aSelector); 
  4. //判斷, 手動(dòng)生成簽名 
  5. if([sel isEqualToString:@"run"]){ 
  6. return [NSMethodSignature signatureWithObjCTypes:"v@:"]; 
  7. }else
  8. return [super methodSignatureForSelector:aSelector]; 

拿到簽名 

  1. - (void)forwardInvocation:(NSInvocation *)anInvocation OBJC_SWIFT_UNAVAILABLE(""){ 
  2. NSLog(@"---%@---",anInvocation); 
  3. return [super forwardInvocation:anInvocation]; 

此時(shí)我們的po的簽名輸出為” return value: {v} void target: {@} 0x600000016ba0 selector: {:} run “

拿到消息轉(zhuǎn)發(fā)簽名 

  1. - (void)forwardInvocation:(NSInvocation *)anInvocation OBJC_SWIFT_UNAVAILABLE(""){ 
  2. NSLog(@"---%@---",anInvocation); 
  3. //取到消息 
  4. SEL seletor = [anInvocation selector]; 
  5. //轉(zhuǎn)發(fā) 
  6. Mbxb *bxb = [[Mbxb alloc]init]; 
  7. if([bxb respondsToSelector:seletor]){ 
  8. //調(diào)用對(duì)象,進(jìn)行轉(zhuǎn)發(fā) 
  9. [anInvocation invokeWithTarget:bxb]; 
  10. }else
  11. return [super forwardInvocation:anInvocation]; 

小細(xì)節(jié): 拋出異常

假如說我們沒有這個(gè)方法, 同樣是遇到會(huì)崩潰的問題

我們這里來(lái)進(jìn)行一個(gè)異常處理 

  1. - (void)doesNotRecognizeSelector:(SEL)aSelector{ 
  2. NSString *selStr = NSStringFromSelector(aSelector); 
  3. NSLog(@"%@不存在",selStr); 

我們可以在這個(gè)異常處理中一些處理, 比如說彈框

總結(jié)

對(duì)于消息轉(zhuǎn)發(fā)機(jī)制, 我們重新來(lái)梳理一下Demo解析思路

還是三個(gè)方案, 按順序來(lái)走

  1. 動(dòng)態(tài)方法解析
  2. 消息轉(zhuǎn)發(fā)重定向
  3. 生成方法簽名
  4. 拿到簽名轉(zhuǎn)發(fā)消息
  5. 細(xì)節(jié)處理, 拋出異常
  6. 最后獻(xiàn)上一張邏輯圖 

好了, 給大家這個(gè)簡(jiǎn)單demo, 當(dāng)然在代碼中也寫了注釋, 可以去我的git下載, 歡迎star

責(zé)任編輯:未麗燕 來(lái)源: Oboe_b
相關(guān)推薦

2023-10-13 10:44:35

OC消息發(fā)送

2024-09-25 08:32:05

2014-03-04 15:28:32

iOS開發(fā)消息傳遞機(jī)制

2011-05-31 11:55:00

Android 消息機(jī)制

2011-02-21 15:17:45

Qmail

2013-04-11 12:40:16

Android消息機(jī)制

2016-03-02 09:34:03

runtime消息ios開發(fā)

2013-12-16 09:44:01

OpenDayLighSDN網(wǎng)絡(luò)轉(zhuǎn)發(fā)

2011-07-01 15:04:49

Qt 內(nèi)省

2024-10-29 08:34:27

RocketMQ消息類型事務(wù)消息

2024-11-11 13:28:11

RocketMQ消息類型FIFO

2011-04-07 17:27:52

Policing

2010-08-13 14:19:44

Flex綁定機(jī)制

2011-04-07 17:43:37

Shapping

2024-11-14 09:10:13

消費(fèi)者RocketMQ負(fù)載均衡

2011-04-07 17:39:57

Shapping

2017-08-17 15:13:52

PostgreSQL MVCC機(jī)制

2011-04-07 17:54:22

Policing

2011-08-02 18:07:03

iPhone 內(nèi)省 Cocoa

2011-11-23 09:39:33

JavaClassLOader機(jī)制
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)