-
1.動(dòng)態(tài)添加方法在本類實(shí)現(xiàn),而交換方法和動(dòng)態(tài)添加屬性在分類中實(shí)現(xiàn)
- 開(kāi)發(fā)使用場(chǎng)景:如果一個(gè)類方法非常多,加載類到內(nèi)存的時(shí)候也比較耗費(fèi)資源侨嘀,需要給每個(gè)方法生成映射表,可以使用動(dòng)態(tài)給某個(gè)類,添加方法解決惭墓。
- 經(jīng)典面試題:有沒(méi)有使用performSelector,其實(shí)主要想問(wèn)你有沒(méi)有動(dòng)態(tài)添加過(guò)方法而姐。
-
2.控制器中
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// performSelector:動(dòng)態(tài)添加方法
Person *p = [[Person alloc] init];
// 動(dòng)態(tài)添加方法eat:, 并且傳入了對(duì)象@111
// [p performSelector:@selector(eat)];
[p performSelector:@selector(eat:) withObject:@111];
}
-
3.在Person類中
#import "Person.h"
#import <objc/message.h>
@implementation Person
// 定義函數(shù)(即要添加的方法)
// 沒(méi)有返回值,參數(shù)(id,SEL)
// 方法默認(rèn)至少有兩個(gè)參數(shù):id self, SEL _cmd,就是方法調(diào)用者和要添加方法名->sel
// id param1,c語(yǔ)言中沒(méi)有對(duì)象的概念,所以用id來(lái)代替,代表傳入的@111
void aaaa(id self, SEL _cmd, id param1)
{
NSLog(@"調(diào)用eat %@ %@ %@",self,NSStringFromSelector(_cmd),param1);
}
// 默認(rèn)一個(gè)方法都有兩個(gè)參數(shù),self,_cmd,隱式參數(shù)
// self:方法調(diào)用者
// _cmd:調(diào)用方法的編號(hào)
// 動(dòng)態(tài)添加方法,首先實(shí)現(xiàn)這個(gè)resolveInstanceMethod
// resolveInstanceMethod調(diào)用:當(dāng)調(diào)用了沒(méi)有實(shí)現(xiàn)的方法沒(méi)有實(shí)現(xiàn)就會(huì)調(diào)用resolveInstanceMethod
// resolveInstanceMethod作用:就知道哪些方法沒(méi)有實(shí)現(xiàn),從而動(dòng)態(tài)添加方法
// sel:就是指沒(méi)有實(shí)現(xiàn)方法
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
// NSLog(@"%@",NSStringFromSelector(sel));
// 動(dòng)態(tài)添加eat方法
if (sel == @selector(eat:)) {
/*
cls:給哪個(gè)類添加方法
SEL:添加方法的方法編號(hào)是什么(即要添加的方法的方法名)
IMP:方法實(shí)現(xiàn),函數(shù)入口,函數(shù)名(要添加方法的具體實(shí)現(xiàn),用C語(yǔ)言)
types:方法類型(在文檔中搜索Type Encodings, class_addMethod,在表中可查對(duì)應(yīng)的含義)
*/
// @:對(duì)象 :SEL
// 將方法入口,即指針強(qiáng)制轉(zhuǎn)為IMP
class_addMethod(self, sel, (IMP)aaaa, "v@:@");
// 處理完
return YES;
}
return [super resolveInstanceMethod:sel];
}
@end
-
4.部分Type Encodings
D8BD4D86-8C1E-4033-9A0A-64997E604087.png