奔跑吧 iOS

工欲善其事,必先利其器系列之 Runtime 实现Notifi

2017-09-04  本文已影响5人  SmileFans

SmileNotification

导读:

如果不用Notification,是否能实现Notification消息的接收与发送呢? 尝试着用runtime试验了一把,答案是可以的,不用考虑烦人的销毁delloc通知,无需考虑发送通知所带的参数,可随意自定义类型,model,字符串,数组等等,只需要对应住消息的标识Key,即可实现
下面是尝试过程


在runtime 中:

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

这两个方法可以让一个对象和另一个对象关联,就是说一个对象可以保持对另一个对象的引用,并获取那个对象。
objc_setAssociatedObject来把一个对象与另外一个对象进行关联。该函数需要四个参数:源对象,关键字,关联的对象和一个关联策略。当然,此处的关键字和关联策略是需要进一步讨论的。
  ■  关键字是一个void类型的指针。每一个关联的关键字必须是唯一的。通常都是会采用静态变量来作为关键字。
  ■  关联策略表明了相关的对象是通过赋值,保留引用还是复制的方式进行关联的;还有这种关联是原子的还是非原子的。这里的关联策略和声明属性时的很类似。这种关联策略是通过使用预先定义好的常量来表示的。
  

思路来了,那么就实现以下试试,既然是关联对象,那就做一个中间代理层,负责消息交互

@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;
    
    
    /**
     发送消息
     @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

在需要用到消息的地方,注册通知,根据相应的receiverKey通过category绑定对象,并在接收地方实现代理方法即可,

通知中心有了,下面就是要写一个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{
    
    //将自己设置成为代理
    self.SmileMessageCenterDelegate = self;
    if (!CHECK_VALID_STRING(receiverKey)) {
        receiverKey = [self getClassName];
    }
    
    [SmileNotificationHelper add_MessageReceiver:self.SmileMessageCenterDelegate
                            receiverKey:receiverKey];
    
}

#pragma mark - 发送消息
- (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]);
    
}


发送者:

[self send_Message:@"💗--晨阳是个Gay~" messageId:SmileMessageTestView_Other receiverKey:@"MessageTestView"];

接受者:

//注册

 [self register_MessageReceiverWithKey:@"MessageTestView"];

//实现代理方法:

//
根据不同的标识实现不同的方法

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

        _textField1.text = @"🐘这是一个刷新的值的通知";
    
        
    }else if ([msgId isEqualToString:SmileMessageTestView_Reset]){

           _textField1.text = @"✈️这是一个重置的通知";
        
    }
    else if ([msgId isEqualToString:SmileMessageTestView_Other]){
        
        
        //message 可带任何类型
         NSString *messageModel = (NSString *)message;
        
        _textField1.text = messageModel;
        
    }
  }

demo传送门:

项目传送门
项目地址
https://github.com/SmileMee/SmileNotification

上一篇下一篇

猜你喜欢

热点阅读