1. 程式人生 > >runtime如何通過selector找到對應的IMP地址?(分別考慮類方法和例項方法)

runtime如何通過selector找到對應的IMP地址?(分別考慮類方法和例項方法)

最近在看《招聘一個靠譜的iOS》,這是其中的一個題目,看著別人的解答不是很詳細,於是就想弄清楚一些,通過查找了一些資料並且自己寫了一些測試的程式碼,在這裡做個總結!

概述

類物件中有類方法和例項方法的列表,列表中記錄著方法的名詞、引數和實現,而selector本質就是方法名稱,runtime通過這個方法名稱就可以在列表中找到該方法對應的實現。

struct objc_class {
    Class isa  OBJC_ISA_AVAILABILITY;

#if !__OBJC2__
    Class super_class                                        
    const
char *name long version long info long instance_size struct objc_ivar_list *ivars struct
objc_method_list **methodLists struct objc_cache *cache struct objc_protocol_list *protocols #endif } OBJC2_UNAVAILABLE;

這裡聲明瞭一個指向struct objc_method_list指標的指標,可以包含類方法列表和例項方法列表

具體實現

在尋找IMP的地址時,runtime提供了兩種方法

IMP class_getMethodImplementation(Class
cls, SEL name); IMP method_getImplementation(Method m)

而根據官方描述,第一種方法可能會更快一些

@note \c class_getMethodImplementation may be faster than \c method_getImplementation(class_getInstanceMethod(cls, name)).

對於第一種方法而言,類方法和例項方法實際上都是通過呼叫class_getMethodImplementation()來尋找IMP地址的,不同之處在於傳入的第一個引數不同

類方法(假設有一個類A)

class_getMethodImplementation(objc_getMetaClass("A"),@selector(methodName));

例項方法

class_getMethodImplementation([A class],@selector(methodName));

通過該傳入的引數不同,找到不同的方法列表,方法列表中儲存著下面方法的結構體,結構體中包含這方法的實現,selector本質就是方法的名稱,通過該方法名稱,即可在結構體中找到相應的實現。

struct objc_method {
    SEL method_name                                      
    char *method_types                                       
    IMP method_imp                                           
}

而對於第二種方法而言,傳入的引數只有method,區分類方法和例項方法在於封裝method的函式

類方法

Method class_getClassMethod(Class cls, SEL name)

例項方法

Method class_getInstanceMethod(Class cls, SEL name)

最後呼叫IMP method_getImplementation(Method m) 獲取IMP地址

實驗

這裡有一個叫Test的類,在初始化方法裡,呼叫了兩次getIMPFromSelector:方法,第一個aaa方法是不存在的,test1和test2分別為例項方法和類方法

然後我同時例項化了兩個Test的物件,列印資訊如下

大家注意圖中紅色標註的地址出現了8次:0x1102db280,這個是在呼叫class_getMethodImplementation()方法時,無法找到對應實現時返回的相同的一個地址,無論該方法是在例項方法或類方法,無論是否對一個例項呼叫該方法,返回的地址都是相同的,但是每次執行該程式時返回的地址並不相同,而對於另一種方法,如果找不到對應的實現,則返回0,在圖中我做了藍色標記。

還有一點有趣的是class_getClassMethod()的第一個引數無論傳入objc_getClass()還是objc_getMetaClass(),最終呼叫method_getImplementation()都可以成功的找到類方法的實現。
而class_getInstanceMethod()的第一個引數如果傳入objc_getMetaClass(),再呼叫method_getImplementation()時無法找到例項方法的實現卻可以找到類方法的實現。

相關推薦

runtime如何通過selector找到對應IMP地址分別考慮方法例項方法

最近在看《招聘一個靠譜的iOS》,這是其中的一個題目,看著別人的解答不是很詳細,於是就想弄清楚一些,通過查找了一些資料並且自己寫了一些測試的程式碼,在這裡做個總結! 概述 類物件中有類方法和例項方法的列表,列表中記錄著方法的名詞、引數和實現,而selec

Python基礎13:面向物件進階訪問限制,__slots__,property,獲取物件資訊,屬性例項屬性

一,訪問限制 原因:直接操作物件屬性有兩個缺點:無法保證資料安全性,無法進行引數校驗。 示例: class fruit(object): #定義一個類 def __init__(self,name): #定義屬性name

python程式設計變數例項變數

【 宣告:版權所有,歡迎轉載,請勿用於商業用途。 聯絡信箱:feixiaoxing @163.com】     關於類變數和例項變數,一直不是很清楚。所以,想做幾個實驗,徹底解決這個問題。為此,我們設計了三個實驗。 1、直接引用類變數 import

【程式碼】K-means聚詳解及實現 Matlab聚工具箱自己實現

一. 聚類 先說說聚類。顧名思義,就是有一團資料,根據某種準則把相似的資料分別聚在一起,形成不同的類別(每個類別稱為一簇)。聚類是一種無監督的演算法。所謂無監督就是說,雖然聚類把物體分類到了不同的簇,只能知道哪些資料是屬於同一類的,至於這一類資料到底是什麼,並不知道。

在python3.6環境下使用os.walk遍歷所有的中文資料夾,並且列印對應地址包括os.walk的語法

首先來看看資料夾的分佈和文字內容可以看到保險資料夾下有三個資料夾,每個資料夾中又包含許多TXT文字,所有程式碼如下# -*-coding:utf-8-*- import os for root,dirs,files in os.walk(r"C:\Users\ME\Deskt

通過IP獲取使用者所在地址後臺方式)

mavenJSON包匯入配置:   <dependency>     <groupId>org.json</groupId>     <artifactId>json</artifactId>     <ve

異常發生後如何將log裡對應地址轉換為所在的檔案行號

這個轉換需要藉助一個GNU工具:arm-linux-androideabi-addr2line(ARM 32位版本)或aarch64-linux-android-addr2line(ARM 64位版本) 工具位置(具體以實際目錄位置為準): ARM 32位版本:prebuilts/gcc/linu

Leet515.在每個樹行中最大值Find Largest Value in Each Tree Row

/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; *

Java-基於百度API的圖片文字識別支援中文,英文中英文混合貨運APP開發上海捌躍網路科技有限公司

PS: 基於Java 1.8 版本控制:maven 使用之前需要獲取對應的專案API_KEY,SECRET_KEY,這些引數在使用API的時候必須用到,用於生成access_token。 如何獲取這些引數:在百度開發者中心申請一個“通用文字識別”專案,然後就可

ionic3自定義管道,匯入使用後報錯不到管道The pipe 'wordPlacePipe' could not be found的坑

最近在做一個app專案。使用了ionic3框架,中間要做一個輸入框輸入字元在一些已知的字元中篩選並高亮提示的搜尋功能,我選擇使用過濾的方法來實現,在angular4-ionic3中也叫管道。 在專案中建立管道命令列:ionic g pipe wordPlace 建立完成後

ioremap 函式對映操作已知的實體地址暫存器、埠、IO

NAME ioremap - map bus memory into CPU space SYNOPSIS void __iomem * ioremap (unsigned

通過 JavaMail 訪問 Hotmail 郵箱hotmail不提供smtppop3服務

簡介: 相信許多人都有 MSN 聊天工具的帳號,例如 [email protected] ,這個賬號其實也是一個郵件地址,可以進行正常的郵件收發功能,你可以通過網址 http://www.hotmail.com 來訪問和操作這個郵箱進行郵件的收發。但是這個郵箱有一

通過vjudge刷Uva的題目解決Uva網站開啟慢的問題

最近在跟著演算法競賽入門經典刷題,發現Uva網站開啟超級慢,進個主頁面都需要好幾秒。後來發現可以通過vjudge網站刷Uva的題目,很是方便,在這mark一下,順便做一下推薦。 vjudge網址:https://vjudge.net,點選後會進入vjudge網站主頁,如下圖

通過瀏覽器訪問操作Oracle資料庫附Oracle修改使用者名稱密碼

  以前簡單的用過Oracle資料庫,都是用控制檯,通過命令操作的,然後最近學校增加了一門新的課程,又學了一招:通過瀏覽器訪問操作Oracle資料庫。   1.開啟瀏覽器;   2.在位址列輸入“localhost:8080/apex”,回車;   3.已經進入登入頁面,輸

vc獲取mac地址無線網絡卡有線網絡卡

獲取網絡卡的MAC地址的方法很多,如:Netbios,SNMP,GetAdaptersInfo等。經過測試發現 Netbios 方法在網線拔出的情況下獲取不到MAC,而 SNMP 方法有時會獲取多個重複的網絡卡的MAC,試來試去還是 GetAdaptersInfo 方法比較

碩士畢業生工作經驗體會怎樣才能說服你面前的HR

下個月就要離開交大了,這個我呆了將近7年的地方。最後想留下一點關於找工作方面的經驗體會。 從05年考研結束的時候開始找工作,之後知道研究生錄取之後找實習,一直到07年正式找工作,期間我接觸過很多行業,很多人,很多職位。從一開始,我就聽無數人在跟我抱怨,抱怨自己的學校不好,

iOS獲取裝置IP地址WiFi,蜂窩資料兩種情況

以下列舉出iOS下獲取IP地址的常用的兩種方式: 第一種適合在WiFi情況下使用,但是如果切換到蜂窩資料下,則返回資料@“error” 直接呼叫getIPAddress 方法即可: #import <ifaddrs.h> #import <arpa/

java 反射之獲取泛型對象的所有字段與對應的值包括父

date lse 代碼 out lda ble alt http info 上代碼: public static void main(String[] args) throws IntrospectionException { SysUser obj =

詳解C# Tuple VS ValueTuple元組 VS 值元組

edit 成員 擴展 ati art info ets 簡單 ole C# 7.0已經出來一段時間了,大家都知道新特性裏面有個對元組的優化,並且網上也有大量的介紹,這裏利用詳盡的例子詳解Tuple VS ValueTuple(元組類VS值元組),10分鐘讓你更了解Value

走入計算機的第三十八天python的進程協成

三十八 控制流 需要 數據 spa 下一步 微線程 用法 適合 一、進程   1、multiprocessing模塊實現多進程並發。     1.1multiprocessing包是Python中的多進程管理包,與threading.Thread類似,它可以利用multip