標(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);
}