重写通知中心类
笔者重新设计了通知中心类,功能完全与系统的通知中心一致,但有着比系统通知中心更优秀的地方:
1. 注册了通知中心不需要手动移除,如果注册对象自动释放了,在通知中心中注册的信息也会自动消失
2. 传递的参数可以是任何的对象,包括数组,字典等等一切对象
3. 基于NSObject的category扩展而来,使用非常的方便
所有的源码如下:
CustumNotification.h
//
// CustumNotification.h
//
// http://home.cnblogs.com/u/YouXianMing/
//
// Copyright (c) 2014年 Y.X. All rights reserved.
//
#import <Foundation/Foundation.h>
@protocol CustomNotificationProtrol <NSObject>
@optional
- (void)listenCustumNotificationEvent:(id)message;
- (void)listenCustumNotificationEvent:(id)message messageFlag:(id)flag;
@end
SuperNotification.h 与 SuperNotification.m
//
// SuperNotification.h
//
// http://home.cnblogs.com/u/YouXianMing/
//
// Copyright (c) 2014年 Y.X. All rights reserved.
//
#import <Foundation/Foundation.h>
@protocol CustomNotificationProtrol;
@interface SuperNotification : NSObject
+ (void)delegate:(id<CustomNotificationProtrol>)target name:(NSString *)name;
+ (void)message:(id)msg toName:(NSString *)name;
+ (void)message:(id)msg messageFlag:(id)flag toName:(NSString *)name;
+ (void)remove:(id<CustomNotificationProtrol>)target name:(NSString *)name;
+ (id)objectByName:(NSString *)name;
+ (NSString *)nameByObject:(id)obj;
@end
//
// SuperNotification.m
//
// http://home.cnblogs.com/u/YouXianMing/
//
// Copyright (c) 2014年 Y.X. All rights reserved.
//
#import "SuperNotification.h"
#import "CustomNotificationProtrol.h"
static NSMapTable *weakNotification = nil;
@implementation SuperNotification
+ (void)initialize
{
if (self == [SuperNotification class])
{
// 强引用key值弱引用object(key值不会被释放)
weakNotification = [NSMapTable strongToWeakObjectsMapTable];
}
}
+ (void)delegate:(id<CustomNotificationProtrol>)target name:(NSString *)name
{
// 将对象添加进weak字典
if ([weakNotification objectForKey:name] == nil)
{
// 添加对象进weak集合
[weakNotification setObject:target forKey:name];
}
}
+ (void)message:(id)msg toName:(NSString *)name
{
// 如果name以及source为空
if (name == nil)
{
return;
}
// 获取抽象类
id<CustomNotificationProtrol> object = [weakNotification objectForKey:name];
if (object == nil)
{
// 没有根据键值找到对象(没有添加对象或者对象已经被释放了),则移除掉这个键值
[weakNotification removeObjectForKey:name];
}
else
{
// 判断抽象类能否执行方法
if ([object respondsToSelector:@selector(listenCustumNotificationEvent:)] == YES)
{
// 能执行方法则执行这个方法
[object listenCustumNotificationEvent:msg];
}
}
}
+ (void)message:(id)msg messageFlag:(id)flag toName:(NSString *)name
{
// 如果name以及source为空
if (name == nil && flag == nil)
{
return;
}
// 获取抽象类
id<CustomNotificationProtrol> object = [weakNotification objectForKey:name];
if (object == nil)
{
// 没有根据键值找到对象(没有添加对象或者对象已经被释放了),则移除掉这个键值
[weakNotification removeObjectForKey:name];
}
else
{
// 判断抽象类能否执行方法
if ([object respondsToSelector:@selector(listenCustumNotificationEvent:messageFlag:)] == YES)
{
// 能执行方法则执行这个方法
[object listenCustumNotificationEvent:msg messageFlag:flag];
}
}
}
+ (void)remove:(id<CustomNotificationProtrol>)target name:(NSString *)name
{
if (target == nil || name == nil)
{
return;
}
// 移除掉键值
[weakNotification removeObjectForKey:name];
}
+ (id)objectByName:(NSString *)name
{
return [weakNotification objectForKey:name];
}
+ (NSString *)nameByObject:(id)obj
{
NSString *myKey = nil;
// 获取所有key值
NSEnumerator * enu = [weakNotification keyEnumerator];
// 遍历key值
NSString *key = nil;
while (key = [enu nextObject])
{
// 根据key值取出对象
id tmpObj = [weakNotification objectForKey:key];
// 比较对象
if ([tmpObj isEqual:obj])
{
myKey = key;
break;
}
}
return myKey;
}
@end
NSObject+CustomNotification.h 与 NSObject+CustomNotification.m
//
// NSObject+CustomNotification.h
//
// http://home.cnblogs.com/u/YouXianMing/
//
// Copyright (c) 2014年 Y.X. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "CustomNotificationProtrol.h"
/*
个人定制的通知中心是需要实现以下两个方法你才能接受到通知
- (void)listenCustumNotificationEvent:(id)message;
- (void)listenCustumNotificationEvent:(id)message messageFlag:(id)flag;
*/
@interface NSObject (CustomNotification)
@property (nonatomic, strong) NSString *custumNotificationName;
- (void)registerCustomNotificationByName:(NSString *)name;
- (void)sendMessage:(id)msg toName:(NSString *)name;
- (void)sendMessage:(id)msg messageFlag:(id)flag toName:(NSString *)name;
- (void)removeCustomNotificationByName:(NSString *)name;
- (NSString *)getRegisterNotificationName;
+ (NSString *)ClassName;
- (NSString *)className;
@end
//
// NSObject+CustomNotification.m
//
// http://home.cnblogs.com/u/YouXianMing/
//
// Copyright (c) 2014年 Y.X. All rights reserved.
//
#import "NSObject+CustomNotification.h"
#import "SuperNotification.h"
#import <objc/runtime.h>
@interface NSObject ()<CustomNotificationProtrol>
@property (nonatomic, assign) id<CustomNotificationProtrol> customNotificationProtrolDelegate;
@end
@implementation NSObject (CustomNotification)
static char customNotificationProtrolDelegateFlag;
- (void)setCustomNotificationProtrolDelegate:(id<CustomNotificationProtrol>)customNotificationProtrolDelegate
{
objc_setAssociatedObject(self, &customNotificationProtrolDelegateFlag,
nil, OBJC_ASSOCIATION_ASSIGN);
objc_setAssociatedObject(self, &customNotificationProtrolDelegateFlag,
customNotificationProtrolDelegate,
OBJC_ASSOCIATION_ASSIGN);
}
- (id<CustomNotificationProtrol>)customNotificationProtrolDelegate
{
return objc_getAssociatedObject(self, &customNotificationProtrolDelegateFlag);
}
static char customNotificationNameFlag;
- (void)setCustumNotificationName:(NSString *)custumNotificationName
{
objc_setAssociatedObject(self, &customNotificationNameFlag,
nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
objc_setAssociatedObject(self, &customNotificationNameFlag,
custumNotificationName,
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSString *)custumNotificationName
{
return objc_getAssociatedObject(self, &customNotificationNameFlag);
}
- (void)registerCustomNotificationByName:(NSString *)name
{
// 将自己设置成为代理
self.customNotificationProtrolDelegate = self;
if (name == nil)
{
[SuperNotification delegate:self.customNotificationProtrolDelegate
name:NSStringFromClass([self class])];
}
else
{
[SuperNotification delegate:self.customNotificationProtrolDelegate
name:name];
}
}
- (void)sendMessage:(id)msg toName:(NSString *)name
{
[SuperNotification message:msg
toName:name];
}
- (void)sendMessage:(id)msg messageFlag:(id)flag toName:(NSString *)name
{
[SuperNotification message:msg
messageFlag:flag
toName:name];
}
- (void)removeCustomNotificationByName:(NSString *)name
{
if (name == nil)
{
[SuperNotification remove:self.customNotificationProtrolDelegate
name:NSStringFromClass([self class])];
}
else
{
[SuperNotification remove:self.customNotificationProtrolDelegate
name:name];
}
}
- (NSString *)getRegisterNotificationName
{
return [SuperNotification nameByObject:self];
}
+ (NSString *)ClassName
{
// 返回类名
return NSStringFromClass(self);
}
- (NSString *)className
{
// 返回类名
return NSStringFromClass([self class]);
}
@end
以下是使用源码:
//
// RootViewController.m
// SuperNotification
//
// Copyright (c) 2014年 Y.X. All rights reserved.
//
#import "RootViewController.h"
#import "NSObject+CustomNotification.h"
@interface RootViewController ()
@end
@implementation RootViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// 注册通知中心
[self registerCustomNotificationByName:nil];
// 发送通知信息(任意对象都可以发布通知信息)
[@"YouXianMing" sendMessage:@[@"YouXianMing", @"YouHongMing"]
messageFlag:[@"YouXianMing" className]
toName:[self className]];
}
// 监听通知信息
- (void)listenCustumNotificationEvent:(id)message messageFlag:(id)flag
{
NSLog(@"%@ - %@", flag, message);
}
@end
以下简短的说一下设计细节:
1. 协议文件是一个单独的文件
2. 协议对象可以看做一个对象
3. runtime支持协议对象的category的扩展
4. category中奖对象自己设置成代理
5. 使用时注意要将协议的方法实现了