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子类实现的关键所在