iOS设计模式 - 代理
原理图
说明
1. 代理模式大家都用过,但用抽象基类NSProxy实现代理估计鲜有人用
2. 本人用NSProxy实现了代理模式,对于理解消息转发机制有点帮助
源码
https://github.com/YouXianMing/iOS-Design-Patterns
//
// AbstractProxy.h
// AppProxy
//
// Created by YouXianMing on 15/8/4.
// Copyright (c) 2015年 YouXianMing. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface AbstractProxy : NSProxy
/**
* 被代理对象
*/
@property (nonatomic, weak) id customer;
/**
* 代理客户
*
* @param customer 实现了某种协议的客户
*
* @return 代理对象
*/
- (instancetype)initWithCustomer:(id)customer;
@end
//
// AbstractProxy.m
// AppProxy
//
// Created by YouXianMing on 15/8/4.
// Copyright (c) 2015年 YouXianMing. All rights reserved.
//
#import <objc/runtime.h>
#import "AbstractProxy.h"
#import "AbstractExcute.h"
@implementation AbstractProxy
- (instancetype)initWithCustomer:(id)customer {
self.customer = customer;
return self;
}
#pragma mark - NSProxy
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
if ([self.customer respondsToSelector:aSelector]) {
return [self.customer methodSignatureForSelector:aSelector];
} else {
AbstractExcute *excute = [AbstractExcute shareInstance];
return [excute methodSignatureForSelector:NSSelectorFromString(@"nullExcute:")];
}
}
- (void)forwardInvocation:(NSInvocation *)invocation {
SEL selector = [invocation selector];
if ([self.customer respondsToSelector:selector]) {
[invocation setTarget:self.customer];
[invocation invoke];
} else {
NSString *selectorString = NSStringFromSelector(invocation.selector);
invocation.selector = NSSelectorFromString(@"nullExcute:");
AbstractExcute *excute = [AbstractExcute shareInstance];
[invocation setTarget:excute];
const char *className = class_getName([self class]);
NSArray *classNameArray = nil;
if (self.customer) {
classNameArray = @[[NSString stringWithUTF8String:className], selectorString, @""];
} else {
classNameArray = @[[NSString stringWithUTF8String:className], selectorString];
}
[invocation setArgument:&classNameArray atIndex:2];
[invocation invoke];
}
}
@end
//
// AbstractExcute.h
// AppProxy
//
// Created by YouXianMing on 15/8/4.
// Copyright (c) 2015年 YouXianMing. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface AbstractExcute : NSObject
+ (instancetype)shareInstance;
@end
//
// AbstractExcute.m
// AppProxy
//
// Created by YouXianMing on 15/8/4.
// Copyright (c) 2015年 YouXianMing. All rights reserved.
//
#import "AbstractExcute.h"
@implementation AbstractExcute
+ (instancetype)shareInstance {
static AbstractExcute *sharedAbstractExcute = nil;
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
sharedAbstractExcute = [[self alloc] init];
});
return sharedAbstractExcute;
}
- (void)nullExcute:(NSArray *)className {
if (className.count == 3) {
NSLog(@"%@ 设置了代理,但该代理没有实现 %@ 方法", className[0], className[1]);
} else {
NSLog(@"%@ 没有设置代理,方法 %@ 没有执行", className[0], className[1]);
}
}
@end
细节
NSProxy子类实现的关键所在