class_addMethod官方檔案如下:
/**
* Adds a new method to a class with a given name and implementation.
*
* @param cls The class to which to add a method.
* @param name A selector that specifies the name of the method being added.
* @param imp A function which is the implementation of the new method. The function must take at least two arguments—self and _cmd.
* @param types An array of characters that describe the types of the arguments to the method.
*
* @return YES if the method was added successfully, otherwise NO
* (for example, the class already contains a method implementation with that name).
*
* @note class_addMethod will add an override of a superclass's implementation,
* but will not replace an existing implementation in this class.
* To change an existing implementation, use method_setImplementation.
*/
OBJC_EXPORT BOOL
class_addMethod(Class _Nullable cls, SEL _Nonnull name, IMP _Nonnull imp,
const char * _Nullable types)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
描述就是:給一個類添加一個新的方法和該方法的具體實作
BOOL: 回傳值,YES:方法添加成功 ;NO:方法添加失敗
引數:
1、Class cls
cls :要添加新方法的那個類;
傳的型別 [類名 class]
實體方法,傳入CLass;類方法,傳入MetaClss;可以這樣理解,OC里的Class里的加號方法,相當于該類的MetalClas的實體方法,類呼叫類方法,和物件呼叫實體方法,其實底層實作都是一樣的,類也是物件,
2、SEL name
name :要添加的方法名;
添加的方法在本類里面叫的名字,但是方法的格式一定要和你需要添加的方法的格式一樣,比如有無引數
傳的型別 @selector(方法名)
3、IMP imp
實作這個方法的函式
imp:指向實作方法的指標 就是要添加的方法的實作部分
IMP就是Implementation的縮寫,它是指向一個方法實作的指標,每一個方法都有一個對應的IMP,這里需要的是IMP,所以不能直接寫方法,需要用到一個方法:class_getMethodImplementation
SEL就是一個函式的宣告方法,而IMP就是這個方法的實作,也就是一個函式的指標
傳的型別
(1)C語言寫法:(IMP)方法名 ,舉例如下:
不帶引數:
//C語言函式
void startEngine(id self, SEL _cmd) {
NSLog(@"my car starts the engine");
}
這是一個 C 語言的函式,它至少包含了 self 和 _cmd 兩個引數(self 代表著函式本身,而 _cmd 則是一個 SEL 資料體,包含了具體的方法地址),如果要在這個方法中新增引數如下
帶引數:
//C語言函式
void startEngine(id self, SEL _cmd, NSString *brand) {
NSLog(@"my %@ car starts the engine", brand);
}
@implementation Car (myCar)
+ (BOOL)resolveInstanceMethod:(SEL)sel {
if (sel == @selector(drive)) {
class_addMethod([self class], sel, (IMP)startEngine, "v@:@");
return YES;
}
return [super resolveInstanceMethod:sel];
}
@end
只要在那兩個必須的引數之后添加所需要的引數和型別就可以了,回傳值同理,只要把方法名之前的 void 修改成我們想要的回傳型別即可
(2)OC的寫法:class_getMethodImplementation(self,@selector(方法名:)){ };如下:
OBJC_EXPORT IMP class_getMethodImplementation(Class cls, SEL name)
__OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);
這個方法也是runtime的方法,就是獲得對應的方法的指標,也就是IMP,
OC寫法舉例如下:
@implementation Car (myCar)
+ (BOOL)resolveInstanceMethod:(SEL)sel {
if (sel == @selector(drive)) {
class_addMethod([self class], sel, class_getMethodImplementation(self, @selector(startEngine:)), "s@:@");
return YES;
}
return [super resolveInstanceMethod:sel];
}
- (void)startEngine:(NSString *)brand {
NSLog(@"my %@ car starts the engine", brand);
}
@end
4、const char *types
要添加的方法的回傳值和引數 叫 type encodings ;這里可以參考蘋果官方檔案Type Encodings
"v@:@":v:是添加方法無回傳值 @表示是id(也就是要添加的類) :表示添加的方法型別 @表示:引數型別
比如:”v@:”意思就是這已是一個void型別的方法,沒有引數傳入,
再比如 “i@:”就是說這是一個int型別的方法,沒有引數傳入,
再再比如”i@:@”就是說這是一個int型別的方法,有一個引數傳入,
const char *types含義表如下:
注意點:
用這個方法添加的方法是無法直接呼叫的,必須用performSelector:呼叫,
因為performSelector是運行時系統負責去找方法的,在編譯時候不做任何校驗;如果直接呼叫編譯是會自動校驗,
參考文章:
如何實作類方法“ + (BOOL)resolveClassMethod:(SEL) sel”
iOS Runntime 動態添加類方法并呼叫-class_addMethod
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/305728.html
標籤:其他
上一篇:android概述
下一篇:Android 螢屏解析度適配
