iOS 實(shí)現(xiàn)多代理的方法及實(shí)例代碼
iOS實(shí)現(xiàn)多代理
什么是多代理
用過環(huán)信SDK的同學(xué)應(yīng)該對多代理不陌生了,請看下面代碼:
@method @brief 注冊一個(gè)監(jiān)聽對象到監(jiān)聽列表中 @discussion 把監(jiān)聽對象添加到監(jiān)聽列表中準(zhǔn)備接收相應(yīng)的事件 @param delegate 需要注冊的監(jiān)聽對象 @param queue 通知監(jiān)聽對象時(shí)的線程 @result */ - (void)addDelegate:(id<EMChatManagerDelegate>)delegate delegateQueue:(dispatch_queue_t)queue;
平時(shí)我們寫得比較多的代理:
@property (nonatomic,weak) id<EMChatManagerDelegate>delegate;
寫了上面屬性后系統(tǒng)會默認(rèn)生成set方法:
- (void)setDelegate:(id<EMChatManagerDelegate>)delegate;
通過對兩個(gè)接口的比較就不難看出:單代理只能設(shè)置一個(gè),而多代理可以設(shè)置多個(gè),準(zhǔn)確來說應(yīng)該是多代理可以添加多個(gè)
多代理有什么用
有些同學(xué)可能會問為什么要用多代理?用通知也能實(shí)現(xiàn)多個(gè)對象同時(shí)監(jiān)聽啊。是的,用監(jiān)聽通知的方式也能達(dá)到目的。
舉個(gè)例子:服務(wù)端通過 socket 傳來一個(gè)紅點(diǎn)消息{"type":21,"content":"某某消息"},
現(xiàn)在多個(gè)頁面都想拿到這個(gè)消息來判斷自己是否需要顯示紅點(diǎn)。
用通知實(shí)現(xiàn)
監(jiān)聽通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onReceiveMsg:) name:@"kNotificationName_OnReceiveRedPointMsg" object:nil];
實(shí)現(xiàn)通知方法
- (void)onReceiveRedPointMsg:(NSNotification *)noti {
NSDictionary *info = noti.userInfo;
if ([info[@"type"] integerValue] == 21) {
<#code#>
}
}
用代理實(shí)現(xiàn)
注冊代理
[[RedPointManager sharedInstance] addDelegate:<#(id<RedPointManagerDelegate>)#>]
實(shí)現(xiàn)代理方法
- (void)redPointManagerDidReceive:(RedPointModel *)redPointModel {
if (redPointModel.type == 21) {
<#code#>
}
}
顯然,用代理實(shí)現(xiàn)更直觀明了。
如何實(shí)現(xiàn)多代理
上面提到過setDelegate:(id<EMChatManagerDelegate>)delegate的方式是不可行的,當(dāng)?shù)诙蝧et的時(shí)候第一次設(shè)置的代理就不被持有了。只能通過addDelegate:(id<EMChatManagerDelegate>)delegate 這種方式來實(shí)現(xiàn)。
是不是有點(diǎn)不淡定了,將代理對象add到數(shù)組(或者字典)中,會使對象引用計(jì)數(shù)+1,導(dǎo)致代理對象不能釋放。沒錯(cuò),直接把代理加到數(shù)組中是不可行的。但是要持有多個(gè)代理對象,又要考慮到釋放問題怎么搞??纯雌綍r(shí)寫的代理屬性 @property (nonatomic,weak) id<EMChatManagerDelegate>delegate; 突然想到了用weak修飾不就行了嗎。
所以,可以通過橋接來實(shí)現(xiàn)對多個(gè)代理對象的持有。
這樣就好辦了,數(shù)組持有橋接對象,橋接對象再擁有自己的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)
}
}
}
具體調(diào)用
func action() {
operatDelegate { (delegate) in
if let myDelegate = delegate as? SomeManagerDelegate {
myDelegate.callBack()
myDelegate.callback?(msg: ["msg":"hello world!"])
}
}
}
Demo演示

Demo下載
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
相關(guān)文章
iOS面試中如何優(yōu)雅回答B(yǎng)lock導(dǎo)致循環(huán)引用的問題
iOS實(shí)現(xiàn)翻頁效果動(dòng)畫實(shí)例代碼
iOS開發(fā)之導(dǎo)航欄各種右滑返回失效的解決方法匯總
詳解iOS應(yīng)用UI開發(fā)中的九宮格坐標(biāo)計(jì)算與字典轉(zhuǎn)換模型

