iOS 多播者:一對多模式封裝

描述:git倉庫

iOS delegate秧秉、block屬于一對一的模式象迎。
有時(shí)候需要實(shí)現(xiàn)一對多的需求,通知可以實(shí)現(xiàn)呛踊。但有時(shí)候業(yè)務(wù)關(guān)聯(lián)是很緊密的砾淌,通知的可讀性不是很好。

項(xiàng)目中目前使用的是GCDMulticastDelegate,發(fā)現(xiàn)其有幾個(gè)缺點(diǎn):

  1. GCDMulticastDelegate中都是在消息轉(zhuǎn)發(fā)中進(jìn)行消息調(diào)用谭网,消息轉(zhuǎn)發(fā)在iOS中代價(jià)比較高汪厨。
  2. 其消息調(diào)用都是異步提交到隊(duì)列,導(dǎo)致堆棧信息無法跟蹤愉择。
  3. 庫也比較老了劫乱,偶現(xiàn)閃退。體驗(yàn)不是很好锥涕。
  4. 使用起來不太方便衷戈,需要先定義multiDelegate,添加代理,不用需要移除站楚,使用時(shí)還需要判斷方法是否存在脱惰。
@property(nonatomic, strong) GCDMulticastDelegate <BLEnterpriseManagerDelegate> *multiDelegate;

- (instancetype)init {
    if (self = [super init]) {
        self.multiDelegate = (GCDMulticastDelegate <BLEnterpriseManagerDelegate> *) [[GCDMulticastDelegate alloc] init];
    }
    return self;
}

- (void)addDelegate:(id <BLEnterpriseManagerDelegate>)delegate delegateQueue:(dispatch_queue_t)queue {
    [_multiDelegate addDelegate:delegate delegateQueue:queue];
}

- (void)removeDelegate:(id <BLEnterpriseManagerDelegate>)delegate {
    [_multiDelegate removeDelegate:delegate];
}

if ([self.multiDelegate hasDelegateThatRespondsToSelector:@selector(enterpriseManager:didClearAllOrgs:)]) {
    [self.multiDelegate enterpriseManager:self didClearAllOrgs:YES];
}

思考

一對多就是觀察者模式的使用,完全可以自己實(shí)現(xiàn)搏嗡。

  1. 觀察者使用封裝在了NSObject擴(kuò)展中窿春,任何對象都可以添加觀察者對象。不再需要在被觀察者中聲明什么采盒。
  2. 消息調(diào)用使用了NSInvocation旧乞,不走消息轉(zhuǎn)發(fā)。
  3. 如果不設(shè)置隊(duì)列磅氨,默認(rèn)都回到主線程尺栖;也可指定隊(duì)列。
  4. 方法不存在烦租,不需要外部判斷延赌。內(nèi)部打印錯誤日志,注意觀察叉橱。

方案一

使用

  1. 導(dǎo)入頭文件
    #import "NSObject+BLObserver.h"
  2. 添加觀察者
[_customView wp_addObserver:self];
    
    _observer1 = [WPViewObserver new];
    _observer1.title = @"observer1 ";
    [_customView wp_addObserver:_observer1];
    
    _observer2 = [WPViewObserver new];
    _observer2.title = @"observer2 ";
    [_customView wp_addObserver:_observer2 delegateQueue:dispatch_queue_create("observer2", DISPATCH_QUEUE_SERIAL)];//指定隊(duì)列
  1. 被觀察者通知觀察者:帶參數(shù)調(diào)用
    [self wp_notifyObserverWithAction:@selector(update), nil];
    [self wp_notifyObserverWithAction:@selector(update:), 1,nil];
    [self wp_notifyObserverWithAction:@selector(update:count2:), 1,2,nil];
  1. 觀察者監(jiān)聽
- (void)update:(NSInteger)count{
    NSLog(@"detail update %ld",count);
}

- (void)update:(NSInteger)count count2:(NSInteger)count2{
    NSLog(@"detail update %ld,%ld",count,count2);
}
  1. 退出頁面后內(nèi)存自動釋放
2021-02-06 23:18:16.655618+0800 WPObserver_Example[58471:640255] WPDetailViewController dealloc
2021-02-06 23:18:16.656013+0800 WPObserver_Example[58471:640255] WPViewObserver dealloc observer2
2021-02-06 23:18:16.656214+0800 WPObserver_Example[58471:640255] WPViewObserver dealloc observer1
2021-02-06 23:18:16.656621+0800 WPObserver_Example[58471:640255] WPView dealloc

小結(jié)

  1. 多數(shù)監(jiān)聽的或移除的時(shí)候都是在主線程挫以,如果覺得線程不安全,也可以加個(gè)信號量窃祝。
  2. 觀察者模式使用簡單掐松,要考慮到通用性,多參問題。
  3. 多參要考慮到int,double等基本類型大磺。
  4. weak不持有觀察者抡句,不需要釋放。只管監(jiān)聽杠愧,和通知觀察者待榔。如果有特殊情況,不需要監(jiān)聽了流济,可以調(diào)用[wp_removeObserver]究抓,移除監(jiān)聽;單例的監(jiān)聽者,需要手動移除袭灯。

方案二

以上方案可以實(shí)現(xiàn)通知刺下,調(diào)用wp_notifyObserverWithAction:,不支持泛型稽荧。
方案二去掉多參橘茉,加上線程安全,支持泛型姨丈。

使用

  1. 添加觀察者
- (void)addObserver2{
    [_customView.proxyObserver addObserver:self];
    [_customView.proxyObserver addObserver:_observer1];
    [_customView.proxyObserver addObserver:_observer2 delegateQueue:dispatch_queue_create("observer2", DISPATCH_QUEUE_SERIAL)];//指定隊(duì)列
}
  1. 通知觀察者畅卓,支持泛型
[self.proxyObserver notifyObserver:^(id<WPViewObserver>  _Nonnull target) {
    [target update];
} selector:@selector(update)];

[self.proxyObserver notifyObserver:^(id<WPViewObserver>  _Nonnull target) {
    [target update:1];
} selector:@selector(update:)];

[self.proxyObserver notifyObserver:^(id<WPViewObserver>  _Nonnull target) {
    [target update:1 count2:2];
} selector:@selector(update:count2:)];

[self.proxyObserver notifyObserver:^(id<WPViewObserver>  _Nonnull target) {
    [target updateTitle:@"標(biāo)題" count:4];
} selector:@selector(updateTitle:count:)];
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蟋恬,隨后出現(xiàn)的幾起案子翁潘,更是在濱河造成了極大的恐慌,老刑警劉巖歼争,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拜马,死亡現(xiàn)場離奇詭異,居然都是意外死亡沐绒,警方通過查閱死者的電腦和手機(jī)俩莽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來乔遮,“玉大人扮超,你說我怎么就攤上這事√0梗” “怎么了出刷?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長坯辩。 經(jīng)常有香客問我馁龟,道長,這世上最難降的妖魔是什么濒翻? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任屁柏,我火速辦了婚禮啦膜,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘淌喻。我一直安慰自己僧家,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布裸删。 她就那樣靜靜地躺著八拱,像睡著了一般涯塔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上爹谭,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天诺凡,我揣著相機(jī)與錄音腹泌,去河邊找鬼尔觉。 笑死侦铜,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的配深。 我是一名探鬼主播嫁盲,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼羞秤,長吁一口氣:“原來是場噩夢啊……” “哼左敌!你這毒婦竟也來了矫限?” 一聲冷哼從身側(cè)響起佩抹,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤棍苹,失蹤者是張志新(化名)和其女友劉穎枢里,沒想到半個(gè)月后蹂午,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體豆胸,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡晚胡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年搬泥,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了忿檩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片燥透。...
    茶點(diǎn)故事閱讀 39,688評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡班套,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出吆豹,到底是詐尸還是另有隱情理盆,我是刑警寧澤,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站蘸拔,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏呕乎。R本人自食惡果不足惜陨晶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一湿刽、第九天 我趴在偏房一處隱蔽的房頂上張望褐耳。 院中可真熱鬧,春花似錦雅镊、人聲如沸刃滓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至总寒,卻和暖如春理肺,著一層夾襖步出監(jiān)牢的瞬間哲嘲,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工竣稽, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留霍弹,地道東北人典格。 一個(gè)月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓耍缴,卻偏偏與公主長得像挽霉,于是被迫代替她去往敵國和親侠坎。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評論 2 353

推薦閱讀更多精彩內(nèi)容