我们通过NSProxyDemo案例来更进一步的了解代理模式
创建AbstarctProxy类
AbstarctProxy.h
#import <Foundation/Foundation.h>
@interface AbstarctProxy : NSProxy
// 代理属性
@property (nonatomic, weak) id delegate;
@end
创建空消息垃圾处理类AbstarctSpamMessages
AbstarctSpamMessages.h
#import <Foundation/Foundation.h>
@interface AbstarctSpamMessages : NSObject
+ (instancetype)sharedInstance;
@end
AbstarctSpamMessages.m
#import "AbstarctSpamMessages.h"
@implementation AbstarctSpamMessages
+ (instancetype)sharedInstance
{
static id sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
// 空的垃圾机制方法
- (void)emptySpamMessages:(NSArray *)parameter withString:(NSString *)str{
NSLog(@"处理垃圾消息");
}
@end
AbstarctProxy.m
#import "AbstarctProxy.h"
#import "AbstarctSpamMessages.h"
#import <objc/message.h>
@implementation AbstarctProxy
// 方法签名
- (nullable NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
// 如果支持这个消息,就将这个方法签名返回回去
if ([self.delegate respondsToSelector:sel]) {
return [self.delegate methodSignatureForSelector:sel];
} else {
AbstarctSpamMessages *message = [AbstarctSpamMessages sharedInstance];
return [message methodSignatureForSelector:NSSelectorFromString(@"emptySpamMessages:withString:")];
}
}
// 配发消息
- (void)forwardInvocation:(NSInvocation *)invocation {
// 1. 获取SEL
SEL selector = [invocation selector];
// 2. 判断代理响应
if ([self.delegate respondsToSelector:selector]) {
// 设置代理
[invocation setTarget:self.delegate];
// 执行方法,派发消息
[invocation invoke];
}
else {
// 获取参数
NSString *selectorString = NSStringFromSelector(invocation.selector);
// 1.替换
invocation.selector = NSSelectorFromString(@"emptySpamMessages:withString:");
// 2.再次回去单例对象
AbstarctSpamMessages *message = [AbstarctSpamMessages sharedInstance];
// 3. 设置代理. 代理就是专门处理垃圾数据的一个对象
[invocation setTarget:message];
// 获取当前控制器的类(ContentProxy)
const char *className = class_getName([self class]);
NSArray *parmater = nil;
NSString *str = @"666";
// 判断代理
if (self.delegate) {
parmater = @[[NSString stringWithUTF8String:className], selectorString,str];
} else {
parmater = @[[NSString stringWithUTF8String:className], selectorString];
}
// 因为0 1 被两个隐式参数占用self,_cmd. 分别表示的是target和selector
[invocation setArgument:&parmater atIndex:2];
[invocation setArgument:&str atIndex:3];
// 执行方法,派发消息
[invocation invoke];
}
}
@end
创建MessagesProtocol协议类
#import <Foundation/Foundation.h>
@protocol MessagesProtocol <NSObject>
- (void)helloWorld;
@end
创建ContentProxy抽象类,继承自AbstarctProxy
ContentProxy.h
#import "AbstarctProxy.h"
#import "MessagesProtocol.h"
@interface ContentProxy : AbstarctProxy <MessagesProtocol>
@end
ViewController调用
#import "ViewController.h"
#import "ContentProxy.h"
@interface ViewController () <MessagesProtocol>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
ContentProxy *proxy = [ContentProxy alloc];
proxy.delegate = self;
[proxy helloWorld];
}
@end
当我们传递一个空的方法helloWorld时,就会收到打印日志