標籤:
iOS設計模式 - 代理
原理圖
說明
1. 代理模式大家都用過,但用抽象基類NSProxy實現代理估計鮮有人用
2. 本人用NSProxy實現了代理模式,對於理解訊息轉寄機制有點協助
源碼
https://github.com/YouXianMing/ProxyPattern
//// 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子類實現的關鍵所在
iOS設計模式 - 代理