iOS實現多代理
什麼是多代理
用過環信SDK的同學應該對多代理不陌生了,請看下面代碼:
@method @brief 注冊一個監聽對象到監聽列表中 @discussion 把監聽對象添加到監聽列表中准備接收相應的事件 @param delegate 需要注冊的監聽對象 @param queue 通知監聽對象時的線程 @result */ - (void)addDelegate:(id<EMChatManagerDelegate>)delegate delegateQueue:(dispatch_queue_t)queue;
平時我們寫得比較多的代理:
@property (nonatomic,weak) id<EMChatManagerDelegate>delegate;
寫了上面屬性後系統會默認生成set方法:
- (void)setDelegate:(id<EMChatManagerDelegate>)delegate;
通過對兩個接口的比較就不難看出:單代理只能設置一個,而多代理可以設置多個,准確來說應該是多代理可以添加多個
多代理有什麼用
有些同學可能會問為什麼要用多代理?用通知也能實現多個對象同時監聽啊。是的,用監聽通知的方式也能達到目的。
舉個例子:服務端通過 socket 傳來一個紅點消息{"type":21,"content":"某某消息"},
現在多個頁面都想拿到這個消息來判斷自己是否需要顯示紅點。
用通知實現
監聽通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onReceiveMsg:) name:@"kNotificationName_OnReceiveRedPointMsg" object:nil];
實現通知方法
- (void)onReceiveRedPointMsg:(NSNotification *)noti { NSDictionary *info = noti.userInfo; if ([info[@"type"] integerValue] == 21) { <#code#> } }
用代理實現
注冊代理
[[RedPointManager sharedInstance] addDelegate:<#(id<RedPointManagerDelegate>)#>]
實現代理方法
- (void)redPointManagerDidReceive:(RedPointModel *)redPointModel { if (redPointModel.type == 21) { <#code#> } }
顯然,用代理實現更直觀明了。
如何實現多代理
上面提到過setDelegate:(id<EMChatManagerDelegate>)delegate的方式是不可行的,當第二次set的時候第一次設置的代理就不被持有了。只能通過addDelegate:(id<EMChatManagerDelegate>)delegate 這種方式來實現。
是不是有點不淡定了,將代理對象add到數組(或者字典)中,會使對象引用計數+1,導致代理對象不能釋放。沒錯,直接把代理加到數組中是不可行的。但是要持有多個代理對象,又要考慮到釋放問題怎麼搞。看看平時寫的代理屬性 @property (nonatomic,weak) id<EMChatManagerDelegate>delegate; 突然想到了用weak修飾不就行了嗎。
所以,可以通過橋接來實現對多個代理對象的持有。
這樣就好辦了,數組持有橋接對象,橋接對象再擁有自己的delegate。
class WeakObjectBridge : NSObject { weak var weakObject : AnyObject? override init() { super.init() } init(object:AnyObject?) { super.init() weakObject = object } }
操作代理
func operatDelegate(cb: @escaping (_ delegate:AnyObject?) -> ()){ for weakObjectBridge in self.delegateBridges { DispatchQueue.main.async { cb(weakObjectBridge.weakObject) } } }
具體調用
func action() { operatDelegate { (delegate) in if let myDelegate = delegate as? SomeManagerDelegate { myDelegate.callBack() myDelegate.callback?(msg: ["msg":"hello world!"]) } } }
Demo演示
Demo下載
點擊這裡下載demo.
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!