上一篇我們通過runtime獲取了Objective-C的類的相關信息,現在我們來修改、添加類。
首先來添加成員變量。之前我們獲取了很多關于成員變量的信息,但是添加成員變量并不是ivar或property相關的函數,而是associatedObject相關的函數。
const char* str_key="str key";
NSString* tmp=@"tmp str";
objc_setAssociatedObject(l,str_key,tmp,OBJC_ASSOCIATION_RETAIN_NONATOMIC);
NSString* tmp2=(NSString*)objc_getAssociatedObject(l, str_key);
objc_removeAssociatedObjects(l);
熟悉C++的同學應該都了解多態,這是C++的OOP編程的核心之一。如果我們需要在運行時動態地添加、修改某個方法,需要怎么做?策略模式?在Objective-C中我們可以通過runtime直接添加、修改方法。
① 動態添加方法
這是我們要添加的一個方法:
void add_func(id _self,SEL _cmd,NSString* _str)
{
NSLog(@"add_func:%@\n",_str);
}
添加的代碼如下:
class_addMethod([MyClass class], @selector(addFunc), (IMP)add_func, "v@:@");
[m performSelector:@selector(addFunc) withObject:@"tmp5"];
objc_msgSend(m, @selector(addFunc), @"tmp6");
id (*imp)(id,SEL,id)=(id (*)(id,SEL,id))[m methodForSelector:@selector(addFunc)];
imp(l,@selector(addFunc),@"tmp7");
通過class_addMethod函數可以添加方法,其中最后一個參數是標示方法的返回值與參數的。常用的如下:
v void
@ id
: SEL
# Class
* char*
調用添加的方法不能直接使用[m addFunc]要通過runtime的performSelector,當然也能通過更基礎的objec_msgSend函數或者IMP來調用。
②修改類的方法
//獲得實例方法
Method func1=class_getInstanceMethod([m class], @selector(func1));
Method func2=class_getInstanceMethod([MyClass class], @selector(func2));
method_exchangeImplementations(func1, func2);
//獲得類方法
Method func3=class_getClassMethod([m class], @selector(func3));
Method func4=class_getClassMethod([MyClass class], @selector(func4));
method_exchangeImplementations(func3, func4);
上面的代碼是交換了func1、func2兩個實例方法以及func3、func4兩個類方法。我們也可以通過method_setImplementation函數修改method的IMP。
runtime常見的用法就是這些,更多的函數可以在之前提到的頭文件中搜索或者在Xcode中鍵入class、method等相關前綴來查詢。
如有錯誤,歡迎指出!