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