zoukankan      html  css  js  c++  java
  • 重写通知中心类

    重写通知中心类

    笔者重新设计了通知中心类,功能完全与系统的通知中心一致,但有着比系统通知中心更优秀的地方:

    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. 使用时注意要将协议的方法实现了

  • 相关阅读:
    MyBatis使用总结
    RPC与RMI的区别
    Python Web-第五周-Web Services and XML(Using Python to Access Web Data)
    Python Web-第四周-Programs that Surf the Web(Using Python to Access Web Data)
    Python Web-第三周-Networks and Sockets(Using Python to Access Web Data)
    Python Web-第二周-正则表达式(Using Python to Access Web Data)
    DELL XPS 13 9350 装Win7系统(坑爹)
    手心输入法皮肤制作技巧
    请对照这二十四条逻辑谬误自行打脸(转自知乎谢熊猫专栏)
    Aspose实现Office转PDF (ASP.NET)
  • 原文地址:https://www.cnblogs.com/YouXianMing/p/3902779.html
Copyright © 2011-2022 走看看