多delegate使用
多delegate的使用
一般在我們使用delegate都知道,是一對一的關系。在目前的項目中,有這樣一個需求,在服務端收到了一個下發事件,需要在不同的頁面,不同的VC都收到此事件,并進行相應的處理。當然這個用RAC實現很簡單,但是目前的項目是一個SDK,如果將ReactiveCocoa引入進來,工程會增大很多,這樣明顯是不合理的,這個時候,就想到了多代理這個思路。其實也是從之前寫的proxy代理類的想法而來。
實現思路
主要是利用OC的runtime,將一個代理類作為中間類,當收到服務器下發的通知時,通過調用代理類的方法,在代理類中實現消息轉發機制,將selector轉發給各個代理類。
還是看代碼。
首先,我們是將各個代理存在中間類中,這樣才能轉發到各個代理。
@interface PPSMutableDelegate : NSObject- (void)addDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue;- (void)removeDelegate:(id)delegate delegateQueue:(nullable dispatch_queue_t)delegateQueue;- (void)removeDelegate:(id)delegate;- (void)removeAllDelegates;@end 復制代碼在需要監聽的delegate中 通過addDelegate將代理添加進去就行,加入queue的目的是為了,在某些收到消息的方法中,需要進行一些異步處理。如果要在主線程中處理,直接放dispatch_get_main_queue()就ok
實現
//代理對象和代理隊列持有類 @interface PPSDelegateNode : NSObject@property (nonatomic, weak) id delegate; @property (nonatomic, strong) dispatch_queue_t delegateQueue;- (id)initWithDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue;@end@implementation PPSDelegateNode- (id)initWithDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue {self = [super init];if (self) {_delegate = delegate;_delegateQueue = delegateQueue;}return self; }@end復制代碼這就是一個model類,用來存儲一下delegate
在具體的PPSMutableDelegate實現中,用了一個NSMutableArray用來儲存delegate 在進行消息轉發時,遍歷數組 轉發出去就行,實現也很簡單
在實現消息轉發時,主要是通過
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector; - (void)forwardInvocation:(NSInvocation *)anInvocation; 復制代碼在實現methodSignatureForSelector:方法時,要注意在這個方法中不能返回nil 否則會崩潰的,所以如果delegate中沒有找到實現,可以在當前實現一個空的方法
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {for (PPSDelegateNode *node in self.delegateNodes) {id nodeDelegate = node.delegate;NSMethodSignature *result = [nodeDelegate methodSignatureForSelector:aSelector];if (result != nil) {return result;}}return [[self class] instanceMethodSignatureForSelector:@selector(emptyMethod)]; } 復制代碼實現forwardInvocation:
- (void)forwardInvocation:(NSInvocation *)anInvocation {SEL selector = [anInvocation selector];BOOL foundNilDelegate = NO;for (PPSDelegateNode *node in self.delegateNodes) {id nodeDelegate = node.delegate;if ([nodeDelegate respondsToSelector:selector]) {dispatch_async(node.delegateQueue, ^{[anInvocation invokeWithTarget:nodeDelegate];});} else if (nodeDelegate == nil) {foundNilDelegate = YES;//找到了delegate是空的node 需要移除掉}}if (foundNilDelegate) {NSMutableIndexSet *indexSet = [[NSMutableIndexSet alloc] init];NSUInteger i = 0;for (PPSDelegateNode *node in self.delegateNodes) {id nodeDelegate = node.delegate;if (nodeDelegate == nil) {[indexSet addIndex:i];}i++;}[self.delegateNodes removeObjectsAtIndexes:indexSet];} } 復制代碼注意 還有一個問題需要注意,要重寫當前中間類的doesNotRecognizeSelector:方法,不然如果調用super的這個方法,會造成崩潰
demo地址:github.com/yangqian111…
歡迎關注公眾號:
總結
以上是生活随笔為你收集整理的多delegate使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: kill qz _e epi,eu,ex
- 下一篇: PowerPC中断系统简介(一)