IOS-runtime

標(biāo)簽(空格分隔): IOS-OC


[toc]


#import <objc/runtime.h>

相關(guān)閱讀
http://yulingtianxia.com/blog/2014/11/05/objective-c-runtime/
http://www.cocoachina.com/ios/20150717/12623.html IMP詳解

runtime的作用

轉(zhuǎn)自: http://www.cnblogs.com/gugupluto/p/3159733.html

  • 增加
增加函數(shù):class_addMethod
增加實(shí)例變量:class_addIvar
增加屬性:@dynamic標(biāo)簽,或者class_addMethod,因?yàn)閷傩云鋵?shí)就是由getter和setter函數(shù)組成
增加Protocol:class_addProtocol (說(shuō)實(shí)話我真不知道動(dòng)態(tài)增加一個(gè)protocol有什么用,-_-!!)
  • 獲取
獲取函數(shù)列表及每個(gè)函數(shù)的信息(函數(shù)指針、函數(shù)名等等):class_getClassMethod method_getName ...
獲取屬性列表及每個(gè)屬性的信息:class_copyPropertyList property_getName
獲取類本身的信息,如類名等:class_getName class_getInstanceSize
獲取變量列表及變量信息:class_copyIvarList
獲取變量的值
  • 替換
將實(shí)例替換成另一個(gè)類:object_setClass
將函數(shù)替換成一個(gè)函數(shù)實(shí)現(xiàn):class_replaceMethod
直接通過(guò)char *格式的名稱來(lái)修改變量的值,而不是通過(guò)變量

方法執(zhí)行順序

首先檢查方法緩存->沒(méi)有發(fā)現(xiàn)->檢查方法列表->沒(méi)有發(fā)現(xiàn)->resolveInstanceMethod:方法動(dòng)態(tài)添加->forwardingTargetForSelector:將方法指派給其他對(duì)象調(diào)用->forwardInvocation:得到整個(gè)方法,對(duì)方法進(jìn)行處理->崩潰!!!

使用

獲取類的所有方法

    NSString *className = NSStringFromClass([UIView class]);  
    const char *cClassName = [className UTF8String];  
    id theClass = objc_getClass(cClassName);  
    unsigned int outCount;  
    Method *m =  class_copyMethodList(theClass,&outCount);  
    
    NSLog(@"%d",outCount);  
    for (int i = 0; i<outCount; i++) {  
        SEL a = method_getName(*(m+i));  
        NSString *sn = NSStringFromSelector(a);  
        NSLog(@"%@",sn);  
    }   

方法操作

添加一個(gè)方法

id jx_message(id self,SEL _cmd,... ){
    NSLog(@"瘋了---%@",NSStringFromSelector(_cmd));
    ((id(*)(id, SEL,...))objc_msgSend)(self,NSSelectorFromString(@"XXX"));
    return nil;
}


+(void)load{
    Method init = class_getInstanceMethod(self, @selector(message));
    SEL sel = NSSelectorFromString(@"XXX");
    class_addMethod(self, sel, (IMP)jx_message, "v@:");
    Method se = class_getInstanceMethod(self, sel);
    method_exchangeImplementations(init, se);
}

交換方法

俗稱的hook,這里的self是一個(gè)類類型 也就是+號(hào)方法中的self
交換類方法(+號(hào)方法)

Method orig = class_getClassMethod([self class], @selector(ssssss));
Method obj = class_getClassMethod([self class], @selector(viewDidLoad));
method_exchangeImplementations(orig, obj);

交換實(shí)例方法(-號(hào)方法)

Method orig = class_getInstanceMethod([self class], @selector(ssssss));
Method obj = class_getInstanceMethod([self class], @selector(viewDidLoad));
method_exchangeImplementations(orig, obj);

獲取屬性

獲取實(shí)例屬性列表

id objc = objc_getClass("NSObjec");
unsigned int count;//這個(gè)參數(shù)表示獲取到的數(shù)組下標(biāo)
objc_property_t * propertys = class_copyPropertyList(objc,&count);

從列表中獲取屬性名稱

//ps是數(shù)組指針, *ps表示使用數(shù)組中的第1個(gè)元素
const char * name = property_getName(*ps);

獲取屬性的類型

const char * name = property_getAttributes(*ps);
//返回----T@"NSString",C,N

通過(guò)名稱獲取屬性

//獲取類中的屬性
objc_property_t class_getProperty(Class cls, const char *name);
//獲取協(xié)議中的屬性
objc_property_t protocol_getProperty(Protocol *proto, const char *name, BOOL isRequiredProperty, BOOL isInstanceProperty)

獲取成員變量

class_copyIvarList()

動(dòng)態(tài)添加屬性

static const char MJRefreshHeaderKey = '\0';
//設(shè)置
- (void)setMj_header:(MJRefreshHeader *)mj_header
{
    objc_setAssociatedObject(self, &MJRefreshHeaderKey,mj_header, OBJC_ASSOCIATION_ASSIGN);
}
讀取
- (MJRefreshHeader *)mj_header
{
    return objc_getAssociatedObject(self, &MJRefreshHeaderKey);
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容