一,關聯 objc_get函數
1)創建關聯:objc_setAssociatedObject;該函數須要四個參數:源對象,關鍵字,關聯的對象和一個關聯策略;當源對象銷燬,關聯的對象也會被銷燬測試
源對象: 即綁定者this
關鍵字: 是一個void類型的指針。每個關聯的關鍵字必須是惟一的。一般都是會採用靜態變量來做爲關鍵字spa
關聯的對象: 綁定到源對象身上的對象指針
關聯策略: 代表了相關的對象是經過賦值,保留引用仍是複製的方式進行關聯的;還有這種關聯是原子的仍是非原子的。這裏的關聯策略和聲明屬性時的很相似。這種關聯策略是經過使用預先定義好的常量來表示的。OBJC_ASSOCIATION_ASSIGN、OBJC_ASSOCIATION_RETAIN_NONATOMIC、OBJC_ASSOCIATION_COPY_NONATOMIC等對象
2)獲取相關聯對象:objc_getAssociatedObject:該函數須要兩個參數:源對象,關鍵字ci
3)斷開關聯:斷開關聯是使用objc_setAssociatedObject函數,傳入關聯的對象爲nil值便可。rem
使用函數objc_removeAssociatedObjects能夠斷開全部關聯。一般狀況下不建議使用這個函數,由於他會斷開全部關聯。只有在須要把對象恢復到「原始狀態」的時候纔會使用這個函數。get
例子:cmd
static char objKey;
NSArray * array =[[NSArray alloc] initWidthObjects:@"One", @"Two", @"Three", nil];
objc_setAssociatedObject(array, &objKey, @「對象」, OBJC_ASSOCIATION_RETAIN);
NSString * associatedObject = (NSString *)objc_getAssociatedObject(array, &objKey);
二,class_get
1)得到實例方法: Method m1 = class_getInstanceMethod([對象 class], @selector(對象方法));
2)得到類方法: Method m2 = class_getClassMethod([類 class], @selector(類方法));
3)方法互調: method_exchangeImplementations(m1, m2); 即執行方法m1變成執行是m2,執行方法m2變成執行是m1
例子:
輸出:
三,_cmd的用法
_cmd在Objective-C的方法中表示當前方法的selector,正如同self表示當前方法調用的對象實例。NSStringFromSelector(_cmd)獲得是方法的名稱
例如
static char kExtendVarKey; // 鍵名
- (void)someCategoryMethod
{
NSString *extendVar = objc_getAssociatedObject(self, &kExtendVarKey);
if(!extendVar){
extendVar = @"someText";
objc_setAssociatedObject(self, &kExtendVarKey, extendVar, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
}
等同於下面代碼
- (void)someCategoryMethod
{
NSString *extendVar = objc_getAssociatedObject(self, _cmd);
if(!extendVar){
extendVar = @"someText";
objc_setAssociatedObject(self, _cmd, extendVar, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
}
四,objc_msgSend:該函數至少有兩個參數:objc_msgSend(消息的接受者, selector, param1, param2, …);
1)概念:其實每一個類中都有一張方法列表去存儲這個類中有的方法,當發出objc_msgSend方法時候,就會順着列表去找這個方法是否存在,若是不存在,則向該類的父類繼續查找,直到找到位置。若是始終沒有找到方法,那麼就會進入到消息轉發機制;objc_msgSend被分爲2個過程:1)在cache中尋找SEL。2)在MethodTable尋找SEL。
例子
id returnValue = [someObject messageName:parameter]; ======》 id returnValue = objc_msgSend(someObject,@selector(messageName),paramter)
Id returnValue = [super messageName:parameter]; ======》 id returnValue = objc_msgSendSuper(someObject,@selector(messageName),paramter)