[英]Where are Objective-C selectors registered/stored?
我不太了解Objective-C選擇器。 問題是:Objective-C選擇器存儲在哪里?
Objective-C編譯器和運行時系統如何工作,以便將方法名稱轉換為SEL?
選擇器是“實習”(未加工)的字符串。 運行時維護一個實習字符串池(選擇器)。 如果要實習字符串,則使用C字符串調用sel_getUid()
或sel_registerName()
運行時函數,並返回SEL
類型的不透明句柄(選擇器)。 如果字符串之前已經被中斷,則此選擇器保證等於前一個。 相反,從選擇器中,您可以使用sel_getName()
獲取字符串。 在Cocoa中,您將使用NSSelectorFromString()
和NSStringFromSelector()
,它們對NSString
對象進行操作,而不是使用上述低級運行時函數。
大多數情況下,您不會在程序中間進行字符串和選擇器之間的轉換。 相反,選擇器在編譯時已經被硬編碼了。 當你執行像[foo something: bar]
這樣的方法調用時,它被編譯成類似objc_msgSend(foo, @selector(something:), bar)
,而像@selector(something:)
這樣的選擇器文字將被編譯成對編譯器生成的二進制選擇器表的引用,類似於全局變量。 鏈接模塊時,其選擇器表與主程序的選擇器表合並,以保證選擇器的唯一性。
同樣的問題也困擾了我一段時間。 所以我研究了運行時實現。 這就是我發現的:
所有選擇器都存儲在哈希集中。 如果您已經有一個已注冊的選擇器,它將由objc運行時使用c函數sel_getUid和sel_registerName返回,如果未注冊,它將由相同的函數創建。 它們都具有相同的實現和行為,因為它們正在調用名為__sel_registerName的私有函數。 舊運行時使用指向struct __objc_sel_set的指針來存儲值。
struct __objc_sel_set {
uint32_t _count; /* number of slots used */
uint32_t _capacity; /* maximum number of used slots */
uint32_t _bucketsNum; /* number of slots */
SEL *_buckets; /* can be NULL if not allocated yet */
};
新運行時使用指向struct NXMapTable的指針:
typedef struct _NXMapTable {
/* private data structure; may change */
const struct _NXMapTablePrototype *prototype;
unsigned count;
unsigned nbBucketsMinusOne;
void *buckets;
} NXMapTable OBJC_MAP_AVAILABILITY;
希望這可以幫助。
看看Apples
解釋 :
選擇器是用於選擇要為對象執行的方法的名稱,或者是在編譯源代碼時替換名稱的唯一標識符。 選擇器本身不做任何事情。 它只是識別一種方法。 使選擇器方法名稱與普通字符串不同的唯一因素是編譯器確保選擇器是唯一的。 使選擇器有用的原因是(與運行時一起)它就像一個動態函數指針,對於給定的名稱,它自動指向適用於它所使用的任何類的方法的實現。 假設你有一個方法運行的選擇器,以及類Dog,Athlete和ComputerSimulation(每個都實現了一個方法運行)。 選擇器可以與每個類的實例一起使用以調用其run方法 - 即使每個類的實現可能不同。
如果你看一下@AntoniKedracki的帖子,對methods
和selectors
有一個非常好的解釋。
只是帖子的簡短摘要:
每個objective-c方法都將在c
的struct
中表示。 結構看起來像這樣:
struct objc_method {
SEL method_name
char *method_types
IMP method_imp
}
因此,選擇器將由C
自動從方法名稱創建並保存在SEL method_name
。 如果要訪問objc_method
,則應該包含<objc/runtime.h>
,而不是可以使用運行時方法。
有關更多信息,請查看其他帖子中的鏈接。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.