1. 程式人生 > >iOS中訊息轉發的實現

iOS中訊息轉發的實現

   嗯,執行時,執行時是個好東西。在Objective-C語言中,這個特性可以幫助我們幹很多的事情。

   首先這個特性是把程式碼的決策從編譯和連結時變成執行的時候,這樣我們就可以用這個特性來做一些只有在執行的時候才能做到的東西,具體包括:

   1.swizzling (交換兩個方法的實現)

   2.動態方法(可以在執行的時候對一個類進行方法的增加,我們這篇部落格會主要講解這個)

   3.相關引用(可以把一個類和一個物件使用一個key進行關聯)

   4.內省(判斷一個物件是否可以呼叫一個方法)

   5.使用emoji字元作為方法名

   我們分為兩部分講解訊息轉發,一種是在本類中增加一個對於無法響應的方法的實現,一個是讓另一個物件來響應使用者呼叫的方法。

   我們首先知道,當我們呼叫一個物件的一個方法的時候,會通過*isa真尋找本類中對於該方法的實現IMP,如果本類找不到,則會向父類尋找,當走到NSObject都無法呼叫時,程式會crash掉。但是在crash之前,執行時為我們提供了一個機制就是可以動態地增加這個方法的實現或者讓另一個物件來響應這個方法。

   我們先看看動態增加一個方法吧,比如我們呼叫了物件無法響應的doFoo方法,但是我們在類中有一個方法實現的宣告:

void fooMethod(id obj, SEL _cmd) {
    
    NSLog(@"hehe");
}

   我們希望用這個方法來實現doFoo方法,那麼我們就需要重寫+(
BOOL)resolveInstanceMethod:(SEL)aSEL方法,具體如下:
+(BOOL)resolveInstanceMethod:(SEL)aSEL
{
    if(aSEL == @selector(doFoo)){
        class_addMethod([self class],aSEL,(IMP)fooMethod,"[email protected]:");
        return YES;
    }
    return [super resolveInstanceMethod:aSEL];
}
 

    打一下斷點,我們就可以看到控制檯輸出了"hehe". 

    以上就是動態增加這個方法的實現的過程。

    第二個就是讓另一個物件響應這個方法。

    系統會先走入- (id)forwardingTargetForSelector:(SEL)aSelector方法來進行轉發,我們就需要重寫這個方法,具體如下:

- (id)forwardingTargetForSelector:(SEL)aSelector
{
    if(aSelector == @selector(doFoo)){
        return self.alternativeObject;
    }
    return [super forwardingTargetForSelector:aSelector];
}
  

    系統獲得了這個物件之後,就會使用-(void)forwardInvocation:(NSInvocation *)invocation方法來把方法統一進行執行,具體如下:

-(void)forwardInvocation:(NSInvocation *)invocation
{
    SEL invSEL = invocation.selector;
    
    if([self.alternativeObject respondsToSelector:invSEL]) {
        [invocation invokeWithTarget:self.alternativeObject];
    } else {
        [self doesNotRecognizeSelector:invSEL];
    }
}

   好了,我們在alternativeObject中響應方法打斷點,我們發現執行到了!~

  以上就是要說明的啦~~




相關推薦

iOS訊息轉發實現

   嗯,執行時,執行時是個好東西。在Objective-C語言中,這個特性可以幫助我們幹很多的事情。    首先這個特性是把程式碼的決策從編譯和連結時變成執行的時候,這樣我們就可以用這個特性來做一些只有在執行的時候才能做到的東西,具體包括:    1.swizzling

iOS使用Fastlane實現自動化打包和釋出

Fastlane是一套使用Ruby寫的自動化工具集,用於iOS和Android的自動化打包、釋出等工作,可以節省大量的時間。 Fastlane Github:https://github.com/fastlane/fastlane 官網:https://fast

IOS 使用JavaScriptCore 實現OC與JS的互動

轉: http://www.jianshu.com/p/cdaf9bc3d65d 一、說明 這篇文章記錄自己在研究OC與JS互動中的所得,以及遇到的問題與解決 由於蘋果的稽核時間太漫長,一次稽核不過,那又將進入另一個漫長的稽核期。為了能在開發中方便更新,公司要求在專案

IOS訊息傳遞的8種方式

原創Blog,轉載請註明出處 一 MVC簡介 MVC是將應用中的類組織起來的一種策略。是IOS開發最常用的設計模式,當然,還有諸如MVVM,VIPER等模式,不過不在本文的討論範疇。 MVC代表什麼:Model-View-Controller。 Model:應用是什麼(w

iOS訊息轉發機制

訊息轉發機制 假設說我們宣告一個類, 初始化物件, 並且在此類宣告一個方法, 呼叫方法的時候底層是怎麼處理的呢? 今天我們來簡單模擬測試, 來看道理髮生了什麼 以下是呼叫方法處理的方案圖, 按照方案順序去處理 以下是系統方法

iOS使用dispatch_once實現單例及注意事項

單例模式,是一種常用的軟體設計模式。在它的核心結構中只包含一個被稱為單例的特殊類。通過單例模式可以保證系統中,應用該模式的類一個類只有一個例項。即一個類只有一個物件例項。 在iOS中單例模式實現方式是在類中編寫名為sharedInstance的方法,該方法只會返回全類共

iOSHTML與OC的互動實現

   近日,由於開發需求,涉及到書寫HTML與OC互動的問題。特此做了一番研究,學習到了一點,所以,也就當是做個簡單的筆記。希望可以對有需求的人有幫助,就像我自己學習的時候,總是要到處翻書,到處搜尋。把這些問題解決掉。     以下為正文內容: &

Spring Boot使用WebSocket總結(三):使用訊息佇列實現分散式WebSocket

在上一篇文章(www.zifangsky.cn/1359.html)中我介紹了服務端如何給指定使用者的客戶端傳送訊息,並如何處理對方不線上的情況。在這篇文章中我們繼續思考另外一個重要的問題,那就是:如果我們的專案是分散式環境,登入的使用者被Nginx的反向代理分配到多個不同伺服器,那麼在其中一個伺服器建立了W

iOS一種字串關鍵字檢索高亮的簡易實現

前言 原文連結:kukumalucn.github.io/blog/2018/1… 本文Demo地址:Demo ,喜歡請star 我的Demo集合:JXT_iOS_Demos ,喜歡請star 平時開發中,我們總會不時的和富文字打交道。有時,我們需要用富文字高亮某句話中的某個關鍵字,如果這個關鍵

【android】如何用RedioGroup實現iosTabBar的效果·

一、xml設定 <RadioGroup android:id="@+id/rg_tab" android:layout_width="fill_parent" android:layo

NodeJs 實現IOS APNS 訊息推送服務

公司的專案要求接入伺服器自己接入原生的ISO 推送服務,不再接第三方的SDK,網上也有很多例子講解什麼是APNS ,如何獲取證書,怎麼接入,剛開始還是聽順利的,就是在獲取pem證書上面有些小問題,不過後來ios開發還是解決了,最後他自己做了一個獲取證書的總結。 我做的就是nodejs 服

iOS探索:Runtime之訊息轉發及動態新增方法

在開始之前,我們先來了解下OC中的類與物件 這是一張經典的類的關係示意圖,接下來簡單的介紹一下這張圖 首先當我們建立一個實力物件,會拷貝這個實力物件所屬類的成員變數,但是不會拷貝類定義的方法 當我們傳送訊息給例項物件時,會通過這個例項物件中的isa指標去找到它對應的類,在

Webpack devServer的 proxy 實現跨域(用nodejs代理轉發請求)

假設,我需要請求的介面的入口為 http://www.xxx.com/api, 修改 /config/index.js 配置檔案,修改 dev 選項下 proxyTable 的值為如下: 你需要請求的介面的入口為 http://www.xxx.com/rest, 而程式

springboot使用redis實現非同步訊息通知

為什麼我要用redis來完成非同步訊息,而不是訊息佇列mq之類的? 因為很多的單體專案可能只需要需要一個略微簡單的訊息通知,而不需要如kafka那種完善的訊息佇列, 而且redis在正常的專案中基本都會引入而mq可能較少會引入,所以使用redis來實現訊息通知可以減少不必

SpringBoot使用redis實現訊息佇列

在pom中加入redis依賴: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-r

【精】iOS知識樹,知識點(包括物件、Block、訊息轉發、GCD、執行時、runloop、動畫、Push、KVO、tableview,UIViewController、提交AppStore)

        本文旨在總結iOS知識網路,知識點,該知識網路羅列出常見UIKit、Foundation的物件特點和一些使用經驗,可以看成是一本書;文字編輯採用樹的形式,對知識點進行羅列,並標註一些使用經驗(★)希望對初學者有用或給一些解決疑難雜症者提供思路;某些知識點會深入

一步一步教你理解和實現iOS的鏈式程式設計和函數語言程式設計

談到鏈式程式設計和函數語言程式設計,那Masonry幾乎就是最經典的代表.如: make.top.equalTo(self.view).offset(60) 像這樣top.equalTo(s

iOS 實現方法鏈呼叫

前言 鏈式呼叫(chained calls)是指在函式呼叫返回了一個物件的時候,使得這個呼叫鏈可以不斷的呼叫下去。從概念上可以看做是一環扣一環的鐵鏈,也能被稱作方法鏈呼叫。 假設需求是在網路請求完成之後先篩選過期資料,然後轉換成對應的資料模型進行展示。在Swift中可以直接這麼寫:

iOS TableView 內巢狀 CollectionView 動態高度的實現

在有社交分享平臺屬性的app中,我們經常看見類似有tableview中多圖展示。不管是釋出的表單介面中,還是社交動態的時間線的介面中,都需要根據圖片數量動態變化介面。最近剛好寫了一個這樣的介面,花了點時間寫了個Demo總結一下,希望可以幫助有需要的人。實現Demo效果如下圖。

iOS__block 關鍵字的底層實現原理

在 《iOS面試題集錦(附答案)》 中有這樣一道題目: 在block內如何修改block外部變數?(38題)答案如下: 預設情況下,在block中訪問的外部變數是複製過去的,即:寫操作不對原變數生效。但是你可以加上 __block 來讓其寫操作生效,示例程式碼如下: