Skip to content

Commit

Permalink
add message forwarding demo
Browse files Browse the repository at this point in the history
  • Loading branch information
huangyibiao authored and huangyibiao committed Dec 31, 2015
1 parent 393a9d2 commit 83c78d8
Show file tree
Hide file tree
Showing 10 changed files with 229 additions and 2 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

#文章讲解

[标哥的技术博客](http://www.henishuo.com/runtime-model-dictionary-convert/)
[标哥的技术博客](http://www.henishuo.com/category/runtime/)

#关注我

Expand Down
38 changes: 38 additions & 0 deletions RuntimeDemo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@
698828201C3383F8002363D5 /* HDFArchiveModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 6988281F1C3383F8002363D5 /* HDFArchiveModel.m */; };
698828211C3383F8002363D5 /* HDFArchiveModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 6988281F1C3383F8002363D5 /* HDFArchiveModel.m */; };
698828221C3383F8002363D5 /* HDFArchiveModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 6988281F1C3383F8002363D5 /* HDFArchiveModel.m */; };
6988282B1C34CB9F002363D5 /* HYBCat.m in Sources */ = {isa = PBXBuildFile; fileRef = 6988282A1C34CB9F002363D5 /* HYBCat.m */; };
6988282C1C34CB9F002363D5 /* HYBCat.m in Sources */ = {isa = PBXBuildFile; fileRef = 6988282A1C34CB9F002363D5 /* HYBCat.m */; };
6988282D1C34CB9F002363D5 /* HYBCat.m in Sources */ = {isa = PBXBuildFile; fileRef = 6988282A1C34CB9F002363D5 /* HYBCat.m */; };
698828301C34CBAB002363D5 /* HYBDog.m in Sources */ = {isa = PBXBuildFile; fileRef = 6988282F1C34CBAB002363D5 /* HYBDog.m */; };
698828311C34CBAB002363D5 /* HYBDog.m in Sources */ = {isa = PBXBuildFile; fileRef = 6988282F1C34CBAB002363D5 /* HYBDog.m */; };
698828321C34CBAB002363D5 /* HYBDog.m in Sources */ = {isa = PBXBuildFile; fileRef = 6988282F1C34CBAB002363D5 /* HYBDog.m */; };
698828351C34D476002363D5 /* HYBPig.m in Sources */ = {isa = PBXBuildFile; fileRef = 698828341C34D476002363D5 /* HYBPig.m */; };
698828361C34D476002363D5 /* HYBPig.m in Sources */ = {isa = PBXBuildFile; fileRef = 698828341C34D476002363D5 /* HYBPig.m */; };
698828371C34D476002363D5 /* HYBPig.m in Sources */ = {isa = PBXBuildFile; fileRef = 698828341C34D476002363D5 /* HYBPig.m */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -70,6 +79,12 @@
6980598C1C30D6070021085B /* HYBTestModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HYBTestModel.m; sourceTree = "<group>"; };
6988281E1C3383F8002363D5 /* HDFArchiveModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HDFArchiveModel.h; sourceTree = "<group>"; };
6988281F1C3383F8002363D5 /* HDFArchiveModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HDFArchiveModel.m; sourceTree = "<group>"; };
698828291C34CB9F002363D5 /* HYBCat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HYBCat.h; sourceTree = "<group>"; };
6988282A1C34CB9F002363D5 /* HYBCat.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HYBCat.m; sourceTree = "<group>"; };
6988282E1C34CBAB002363D5 /* HYBDog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HYBDog.h; sourceTree = "<group>"; };
6988282F1C34CBAB002363D5 /* HYBDog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HYBDog.m; sourceTree = "<group>"; };
698828331C34D476002363D5 /* HYBPig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HYBPig.h; sourceTree = "<group>"; };
698828341C34D476002363D5 /* HYBPig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HYBPig.m; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -132,6 +147,7 @@
69654F581C2CDE6600FFB5AC /* RuntimeDemo */ = {
isa = PBXGroup;
children = (
698828281C34CB6A002363D5 /* ForwardMessage */,
6988281D1C3383B4002363D5 /* Archive */,
6980598A1C30D5E90021085B /* Dict-Model */,
69654F5C1C2CDE6600FFB5AC /* AppDelegate.h */,
Expand Down Expand Up @@ -193,6 +209,19 @@
name = Archive;
sourceTree = "<group>";
};
698828281C34CB6A002363D5 /* ForwardMessage */ = {
isa = PBXGroup;
children = (
698828291C34CB9F002363D5 /* HYBCat.h */,
6988282A1C34CB9F002363D5 /* HYBCat.m */,
6988282E1C34CBAB002363D5 /* HYBDog.h */,
6988282F1C34CBAB002363D5 /* HYBDog.m */,
698828331C34D476002363D5 /* HYBPig.h */,
698828341C34D476002363D5 /* HYBPig.m */,
);
name = ForwardMessage;
sourceTree = "<group>";
};
A4EC37D5D490197569607E30 /* Frameworks */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -382,11 +411,14 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
698828301C34CBAB002363D5 /* HYBDog.m in Sources */,
6988282B1C34CB9F002363D5 /* HYBCat.m in Sources */,
69654F611C2CDE6600FFB5AC /* ViewController.m in Sources */,
69654F5E1C2CDE6600FFB5AC /* AppDelegate.m in Sources */,
69654F5B1C2CDE6600FFB5AC /* main.m in Sources */,
698828201C3383F8002363D5 /* HDFArchiveModel.m in Sources */,
6980598D1C30D6070021085B /* HYBTestModel.m in Sources */,
698828351C34D476002363D5 /* HYBPig.m in Sources */,
69654F931C30214500FFB5AC /* UIControl+HYBBlock.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand All @@ -396,8 +428,11 @@
buildActionMask = 2147483647;
files = (
69654F741C2CDE6600FFB5AC /* RuntimeDemoTests.m in Sources */,
6988282C1C34CB9F002363D5 /* HYBCat.m in Sources */,
698828211C3383F8002363D5 /* HDFArchiveModel.m in Sources */,
69654F941C30214500FFB5AC /* UIControl+HYBBlock.m in Sources */,
698828361C34D476002363D5 /* HYBPig.m in Sources */,
698828311C34CBAB002363D5 /* HYBDog.m in Sources */,
6980598E1C30D6070021085B /* HYBTestModel.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand All @@ -407,8 +442,11 @@
buildActionMask = 2147483647;
files = (
69654F7F1C2CDE6600FFB5AC /* RuntimeDemoUITests.m in Sources */,
6988282D1C34CB9F002363D5 /* HYBCat.m in Sources */,
698828221C3383F8002363D5 /* HDFArchiveModel.m in Sources */,
69654F951C30214500FFB5AC /* UIControl+HYBBlock.m in Sources */,
698828371C34D476002363D5 /* HYBPig.m in Sources */,
698828321C34CBAB002363D5 /* HYBDog.m in Sources */,
6980598F1C30D6070021085B /* HYBTestModel.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
Binary file not shown.
17 changes: 17 additions & 0 deletions RuntimeDemo/HYBCat.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// HYBCat.h
// RuntimeDemo
//
// Created by huangyibiao on 15/12/31.
// Copyright © 2015年 huangyibiao. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface HYBCat : NSObject



+ (void)test;

@end
68 changes: 68 additions & 0 deletions RuntimeDemo/HYBCat.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//
// HYBCat.m
// RuntimeDemo
//
// Created by huangyibiao on 15/12/31.
// Copyright © 2015年 huangyibiao. All rights reserved.
//

#import "HYBCat.h"
#import "HYBDog.h"
#import "HYBPig.h"
#import <objc/message.h>

@implementation HYBCat

// 第一步:在没有找到方法时,会先调用此方法,可用于动态添加方法
// 我们不动态添加
+ (BOOL)resolveInstanceMethod:(SEL)sel {
return NO;
}

// 第二步:上一步返回NO,就会进入这一步,用于指定备选响应此SEL的对象
// 千万不能返回self,否则就会死循环
// 自己没有实现这个方法才会进入这一流程,因此成为死循环
- (id)forwardingTargetForSelector:(SEL)aSelector {
return nil;
}

// 第三步:指定方法签名,若返回nil,则不会进入下一步,而是无法处理消息
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
if ([NSStringFromSelector(aSelector) isEqualToString:@"eat"]) {
return [NSMethodSignature signatureWithObjCTypes:"v@:"];
}

return [super methodSignatureForSelector:aSelector];
}

// 当我们实现了此方法后,-doesNotRecognizeSelector:不会再被调用
// 如果要测试找不到方法,可以注释掉这一个方法
- (void)forwardInvocation:(NSInvocation *)anInvocation {

// 我们还可以改变方法选择器
[anInvocation setSelector:@selector(jump)];
// 改变方法选择器后,还需要指定是哪个对象的方法
[anInvocation invokeWithTarget:self];
}

- (void)doesNotRecognizeSelector:(SEL)aSelector {
NSLog(@"无法处理消息:%@", NSStringFromSelector(aSelector));
}

- (void)jump {
NSLog(@"由eat方法改成jump方法");
}

+ (void)test {
HYBDog *dog = [[HYBDog alloc] init];
[dog eat];

HYBPig *pig = [[HYBPig alloc] init];
// [pig performSelector:@selector(eat) withObject:nil afterDelay:0];
((void (*)(id, SEL))objc_msgSend)((id)pig, @selector(eat));

HYBCat *cat = [[HYBCat alloc] init];
[cat performSelector:@selector(eat) withObject:nil afterDelay:0];
}

@end
16 changes: 16 additions & 0 deletions RuntimeDemo/HYBDog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// HYBDog.h
// RuntimeDemo
//
// Created by huangyibiao on 15/12/31.
// Copyright © 2015年 huangyibiao. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface HYBDog : NSObject

// 我们只声明,而不实现
- (void)eat;

@end
33 changes: 33 additions & 0 deletions RuntimeDemo/HYBDog.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//
// HYBDog.m
// RuntimeDemo
//
// Created by huangyibiao on 15/12/31.
// Copyright © 2015年 huangyibiao. All rights reserved.
//

#import "HYBDog.h"
#import <objc/runtime.h>


@implementation HYBDog

// 第一步:实现此方法,在调用对象的某方法找不到时,会先调用此方法,允许
// 我们动态添加方法实现
+ (BOOL)resolveInstanceMethod:(SEL)sel {
// 我们这里没有给dog声明有eat方法,因此,我们可以动态添加eat方法
if ([NSStringFromSelector(sel) isEqualToString:@"eat"]) {
class_addMethod(self, sel, (IMP)eat, "v@:");
return YES;
}

return [super resolveInstanceMethod:sel];
}

// 这个方法是我们动态添加的哦
//
void eat(id self, SEL cmd) {
NSLog(@"%@ is eating", self);
}

@end
13 changes: 13 additions & 0 deletions RuntimeDemo/HYBPig.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// HYBPig.h
// RuntimeDemo
//
// Created by huangyibiao on 15/12/31.
// Copyright © 2015年 huangyibiao. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface HYBPig : NSObject

@end
40 changes: 40 additions & 0 deletions RuntimeDemo/HYBPig.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//
// HYBPig.m
// RuntimeDemo
//
// Created by huangyibiao on 15/12/31.
// Copyright © 2015年 huangyibiao. All rights reserved.
//

#import "HYBPig.h"
#import "HYBDog.h"

@implementation HYBPig

// 第一步,我们不动态添加方法,返回NO
+ (BOOL)resolveInstanceMethod:(SEL)sel {
return NO;
}

// 第二步,备选提供响应aSelector的对象,我们不备选,因此设置为nil,就会进入第三步
- (id)forwardingTargetForSelector:(SEL)aSelector {
return nil;
}

// 第三步,先返回方法选择器。如果返回nil,则表示无法处理消息
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
if ([NSStringFromSelector(aSelector) isEqualToString:@"eat"]) {
return [NSMethodSignature signatureWithObjCTypes:"v@:"];
}

return [super methodSignatureForSelector:aSelector];
}

// 第三步,只有返回了方法签名,都会进入这一步,这一步用户调用方法
// 改变调用对象等
- (void)forwardInvocation:(NSInvocation *)anInvocation {
// 我们改变调用对象为dog
[anInvocation invokeWithTarget:[[HYBDog alloc] init]];
}

@end
4 changes: 3 additions & 1 deletion RuntimeDemo/ViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#import <objc/objc.h>
#import "HYBTestModel.h"
#import "HDFArchiveModel.h"
#import "HYBCat.h"

@interface ViewController ()

Expand All @@ -25,7 +26,8 @@ - (void)viewDidLoad {
// Do any additional setup after loading the view, typically from a nib.

// [HYBTestModel test];
[HDFArchiveModel test];
// [HDFArchiveModel test];
[HYBCat test];
}

- (void)didReceiveMemoryWarning {
Expand Down

0 comments on commit 83c78d8

Please sign in to comment.