1.0、方法的實(shí)現(xiàn)
* 獲取實(shí)例方法:class_getInstanceMethod(Class cls, SEL name)
* 設(shè)置類方法: class_getClassMethod(Class cls, SEL name)
* 獲取方法指針:method_getImplementation(Method m)
* 設(shè)置方法指針:method_setImplementation(Method m, IMP imp) (方法可以重新指向)
* 設(shè)置對(duì)象的類:object_setClass(id obj, Class cls)
1、消息發(fā)送(方法調(diào)用的本質(zhì))
* 注冊(cè)方法:sel_registerName(const char *str),sel_registerName("new")
* 消息發(fā)送:objc_msgSend(id self, SEL op, ...)
* 創(chuàng)建一類:objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes)
objc_msgSend(消息接受者,消息名稱)
objc_msgSend(person, sel_registerName("walk"));
objc_msgSend(objc_getClass("TZPerson"), sel_registerName("addRun"));
Class TZCat = objc_allocateClassPair([NSObject class], "TZCat", 0);
2、消息轉(zhuǎn)發(fā):動(dòng)態(tài)方法解析
- 對(duì)象在收到無法解讀的消息后:調(diào)用
+ (BOOL)resolveInstanceMethod:(SEL)sel來動(dòng)態(tài)為其 添加實(shí)例方法,來處理該選擇。 - 如果尚未實(shí)現(xiàn)的方法是類方法:調(diào)用
+ (BOOL)resolveClassMethod:(SEL)sel來動(dòng)態(tài)為其 添加類方法
//#pragma mark --- 實(shí)例方法 的轉(zhuǎn)換:+ (BOOL)resolveInstanceMethod:(SEL)sel
//#pragma mark --- 實(shí)例方法
+ (BOOL)resolveInstanceMethod:(SEL)sel {
NSLog(@"---resolveInstanceMethod:%s", __func__);
// 元類
// 實(shí)例對(duì)象、類對(duì)象、元類對(duì)象
//例6.2.1:無方法,構(gòu)建一個(gè)方法,并去調(diào)用實(shí)現(xiàn)
if (sel == @selector(walk)) {
//創(chuàng)建實(shí)例方法(向?qū)嵗l(fā)送消息,在類上添加方法)
Method runMethod = class_getInstanceMethod(self, @selector(run));
//方法指針
IMP runIMP = method_getImplementation(runMethod);
//描述方法參數(shù)的類型
const char* types = method_getTypeEncoding(runMethod);
NSLog(@"---(實(shí)例方法)types:%s", types); //v16@0:8 參數(shù)字節(jié)數(shù)16 @從第幾個(gè)字節(jié)開始 :表示第8個(gè)
return class_addMethod(self, sel, runIMP, types);
}
//有方法,去調(diào)用實(shí)現(xiàn),
return [super resolveInstanceMethod:sel];
}
//#pragma mark --- 類方法 的轉(zhuǎn)換:+ (BOOL)resolveClassMethod:(SEL)sel
//#pragma mark --- 類方法
+ (BOOL)resolveClassMethod:(SEL)sel {
NSLog(@"---resolveClassMethod:%s", __func__);
//例6.2.2:(類方法)無方法,構(gòu)建一個(gè)方法,并去調(diào)用實(shí)現(xiàn)
if (sel == @selector(walk)) {
//創(chuàng)建類方法(向類發(fā)送消息,在元類上添加方法)
Method runMethod = class_getInstanceMethod(object_getClass(self), @selector(run));
//方法指針
IMP runIMP = method_getImplementation(runMethod);
//描述方法參數(shù)的類型
const char* types = method_getTypeEncoding(runMethod);
NSLog(@"---(類方法)types:%s", types); //v16@0:8 參數(shù)字節(jié)數(shù)16 @從第幾個(gè)字節(jié)開始 :表示第8個(gè)
return class_addMethod(object_getClass(self), sel, runIMP, types);
}
//有方法,去調(diào)用實(shí)現(xiàn),
return [super resolveClassMethod:sel];
}
3、消息轉(zhuǎn)發(fā):快速轉(zhuǎn)發(fā)、完成轉(zhuǎn)發(fā)
掛載到其他類的方法上。
是否有消息轉(zhuǎn)發(fā):有就去調(diào)用、沒有就崩潰。
既然已經(jīng)問過了,沒有新增方法,那就問問有沒有別人能夠幫忙處理一下:
「v@: 的含義」
v表示方法的返回類型是 void(即沒有返回值)。
@表示方法的第一個(gè)參數(shù)是 id 類型(即 Objective-C 對(duì)象)。
: 表示方法的第二個(gè)參數(shù)是 SEL 類型(即方法選擇器)。
\\實(shí)例方法 處理
- (id) forwardingTargetForSelector:(SEL)aSelector
- (NSMethodSignature* )methodSignatureForSelector:(SEL)aSelector
- (void)forwardInvocation:(NSInvocation *)anInvocation
\\類方法 處理
+ (id) forwardingTargetForSelector:(SEL)aSelector
+ (NSMethodSignature* )methodSignatureForSelector:(SEL)aSelector
+ (void)forwardInvocation:(NSInvocation *)anInvocation
源碼如下:
# ------------------------- (實(shí)例:消息轉(zhuǎn)發(fā)) ---------------------------
# 7.1: 實(shí)例方法(方法掛載,掛載到其他類上)
# 方式一
- (id) forwardingTargetForSelector:(SEL)aSelector {
if (aSelector == @selector(walk7)) {
return [TZDog new];
}
return [super forwardingTargetForSelector:aSelector];
}
# 方式二
# 方法名注冊(cè)
- (NSMethodSignature* )methodSignatureForSelector:(SEL)aSelector {
if (aSelector == @selector(walk7)) {
return [NSMethodSignature signatureWithObjCTypes:"v@:"];
}
return [super methodSignatureForSelector:aSelector];
}
# 消息轉(zhuǎn)發(fā):實(shí)例方法
- (void)forwardInvocation:(NSInvocation *)anInvocation {
//NSLog(@"%s", __func__);
//[anInvocation invokeWithTarget:[TZDog new]]; // 轉(zhuǎn)發(fā)給 其他
// 轉(zhuǎn)發(fā)給 自己
anInvocation.selector = @selector(run);
anInvocation.target = self;
[anInvocation invoke];
}
## ------------------------- (類:消息轉(zhuǎn)發(fā)) ---------------------------
## 7.2:類方法 消息轉(zhuǎn)發(fā)
## 方式一
+ (id) forwardingTargetForSelector:(SEL)aSelector {
if (aSelector == @selector(walk7)) {
//return [TZDog new]; //可以轉(zhuǎn)發(fā)到:類的實(shí)例方法
return [TZDog class];//可以轉(zhuǎn)發(fā)到:類方法
}
return [super forwardingTargetForSelector:aSelector];
}
## 方式二
# 方法名注冊(cè)
+ (NSMethodSignature* )methodSignatureForSelector:(SEL)aSelector {
if (aSelector == @selector(walk7)) {
return [NSMethodSignature signatureWithObjCTypes:"v@:"];
}
return [super methodSignatureForSelector:aSelector];
}
# 消息轉(zhuǎn)發(fā):類方法
+ (void)forwardInvocation:(NSInvocation *)anInvocation {
NSLog(@" 轉(zhuǎn)發(fā)給 其他= %s", __func__);
//[anInvocation invokeWithTarget:[TZDog new]]; //可以轉(zhuǎn)發(fā)到:類的實(shí)例方法
//[anInvocation invokeWithTarget:[TZDog class]]; //可以轉(zhuǎn)發(fā)到:類方法
// 轉(zhuǎn)發(fā)給 自己
anInvocation.selector = @selector(run);
anInvocation.target = self;
[anInvocation invoke];
}
# ------------------------- 結(jié)束(消息轉(zhuǎn)發(fā)) ---------------------------