工欲善其事,必先利其器系列之 Runtime 實(shí)現(xiàn)Notification 傳值

SmileNotification

導(dǎo)讀:

如果不用Notification,是否能實(shí)現(xiàn)Notification消息的接收與發(fā)送呢? 嘗試著用runtime試驗(yàn)了一把,答案是可以的,不用考慮煩人的銷毀delloc通知,無需考慮發(fā)送通知所帶的參數(shù),可隨意自定義類型,model,字符串,數(shù)組等等,只需要對應(yīng)住消息的標(biāo)識(shí)Key,即可實(shí)現(xiàn)
下面是嘗試過程


在runtime 中:

void objc_setAssociatedObject(id object, const void key, id value, objc_AssociationPolicy policy);
id objc_getAssociatedObject(id object, const void key);

這兩個(gè)方法可以讓一個(gè)對象和另一個(gè)對象關(guān)聯(lián),就是說一個(gè)對象可以保持對另一個(gè)對象的引用,并獲取那個(gè)對象。
objc_setAssociatedObject來把一個(gè)對象與另外一個(gè)對象進(jìn)行關(guān)聯(lián)。該函數(shù)需要四個(gè)參數(shù):源對象,關(guān)鍵字,關(guān)聯(lián)的對象和一個(gè)關(guān)聯(lián)策略。當(dāng)然,此處的關(guān)鍵字和關(guān)聯(lián)策略是需要進(jìn)一步討論的。
  ■  關(guān)鍵字是一個(gè)void類型的指針。每一個(gè)關(guān)聯(lián)的關(guān)鍵字必須是唯一的。通常都是會(huì)采用靜態(tài)變量來作為關(guān)鍵字。
  ■  關(guān)聯(lián)策略表明了相關(guān)的對象是通過賦值,保留引用還是復(fù)制的方式進(jìn)行關(guān)聯(lián)的;還有這種關(guān)聯(lián)是原子的還是非原子的。這里的關(guān)聯(lián)策略和聲明屬性時(shí)的很類似。這種關(guān)聯(lián)策略是通過使用預(yù)先定義好的常量來表示的。
  

思路來了,那么就實(shí)現(xiàn)以下試試,既然是關(guān)聯(lián)對象,那就做一個(gè)中間代理層,負(fù)責(zé)消息交互

@protocol SmileMessageCenterDelegate <NSObject>
    
@optional
    
    /**
     接收到message對象
     */
- (void)Smile_ReceiveMessage:(id)message messageId:(NSString *)msgId;
    
@end


@interface SmileNotificationHelper : NSObject

    /**
     添加消息接收者
     @param msgReceiver 消息接收對象
     @param receiverKey 消息接收對象key
     */
+ (void)add_MessageReceiver:(id<SmileMessageCenterDelegate>)msgReceiver receiverKey:(NSString *)receiverKey;
    
    
    /**
     發(fā)送消息
     @param msg 消息對象
     @param msgId 消息id
     @param receiverKey 消息接收對象key
     */
+ (void)send_Message:(id)msg messageId:(NSString *)msgId receiverKey:(NSString *)receiverKey;
    
    
    /**
     刪除消息接收者
     @param receiverKey 消息接收者名
     */
+ (void)remove_MessageReceiverWithKey:(NSString *)receiverKey;
    
    
    
    
@end

在需要用到消息的地方,注冊通知,根據(jù)相應(yīng)的receiverKey通過category綁定對象,并在接收地方實(shí)現(xiàn)代理方法即可,

通知中心有了,下面就是要寫一個(gè)category了

#import "NSObject+SmileNotification.h"
#import "SmileNotificationHelper.h"
#import <objc/runtime.h>
@interface NSObject ()<SmileMessageCenterDelegate>
@property (nonatomic, weak) id<SmileMessageCenterDelegate> SmileMessageCenterDelegate;  
@end
@implementation NSObject (SmileNotification)

- (void)setSmileMessageCenterDelegate:(id<SmileMessageCenterDelegate>)SmileMessageCenterDelegate{
    
    objc_setAssociatedObject(self, @selector(SmileMessageCenterDelegate), SmileMessageCenterDelegate, OBJC_ASSOCIATION_ASSIGN);
}
    
- (id<SmileMessageCenterDelegate>)SmileMessageCenterDelegate{
    
    return objc_getAssociatedObject(self, @selector(SmileMessageCenterDelegate));
}
    
#pragma mark - 注冊消息中心
- (void)register_MessageReceiverWithKey:(NSString *)receiverKey{
    
    //將自己設(shè)置成為代理
    self.SmileMessageCenterDelegate = self;
    if (!CHECK_VALID_STRING(receiverKey)) {
        receiverKey = [self getClassName];
    }
    
    [SmileNotificationHelper add_MessageReceiver:self.SmileMessageCenterDelegate
                            receiverKey:receiverKey];
    
}

#pragma mark - 發(fā)送消息
- (void)send_Message:(id)msg messageId:(NSString *)msgId receiverKey:(NSString *)receiverKey{
    
    if (!CHECK_VALID_STRING(receiverKey)) {
        receiverKey = [self getClassName];
    }
    
    [SmileNotificationHelper send_Message:msg messageId:msgId receiverKey:receiverKey];
    
}
    
 #pragma mark - 移除消息
- (void)remove_MessageReceiverWithKey:(NSString *)receiverKey{
    
    if (!CHECK_VALID_STRING(receiverKey)) {
        receiverKey = NSStringFromClass([self class]);
    }
    
    [SmileNotificationHelper remove_MessageReceiverWithKey:receiverKey];
    
}
    
#pragma mark - private methods
- (NSString *)getClassName{
    
    return NSStringFromClass([self class]);
    
}


發(fā)送者:

[self send_Message:@"??--晨陽是個(gè)Gay~" messageId:SmileMessageTestView_Other receiverKey:@"MessageTestView"];

接受者:

//注冊

 [self register_MessageReceiverWithKey:@"MessageTestView"];

//實(shí)現(xiàn)代理方法:

//
根據(jù)不同的標(biāo)識(shí)實(shí)現(xiàn)不同的方法

- (void)Smile_ReceiveMessage:(id)message messageId:(NSString *)msgId{
    
    if ([msgId isEqualToString:SmileMessageTestView_Update]) {

        _textField1.text = @"??這是一個(gè)刷新的值的通知";
    
        
    }else if ([msgId isEqualToString:SmileMessageTestView_Reset]){

           _textField1.text = @"??這是一個(gè)重置的通知";
        
    }
    else if ([msgId isEqualToString:SmileMessageTestView_Other]){
        
        
        //message 可帶任何類型
         NSString *messageModel = (NSString *)message;
        
        _textField1.text = messageModel;
        
    }
  }

demo傳送門:

項(xiàng)目傳送門
項(xiàng)目地址
https://github.com/SmileMee/SmileNotification

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,506評(píng)論 19 139
  • 國家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說閱讀 12,302評(píng)論 6 13
  • 點(diǎn)擊查看原文 Web SDK 開發(fā)手冊 SDK 概述 網(wǎng)易云信 SDK 為 Web 應(yīng)用提供一個(gè)完善的 IM 系統(tǒng)...
    layjoy閱讀 14,282評(píng)論 0 15
  • *面試心聲:其實(shí)這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個(gè)offer,總結(jié)起來就是把...
    Dove_iOS閱讀 27,581評(píng)論 30 472
  • 自習(xí)歸寢 少無憂,夜窮游。無月清風(fēng)臨渠溝,蠟盡眼倦不覺晚,執(zhí)手倚肩數(shù)星宿。 煩棄筆,解心舟。似水落花逐波流,昔年素...
    南柯夢閱讀 356評(píng)論 0 0

友情鏈接更多精彩內(nèi)容