改善系統的通知中心

改善系統的通知中心設計模式

iOS中的通知中心的實現實現機制是設計模式中的觀察者.post

在不進行任何修改的狀況下,通知中心是這麼使用的.atom

//
//  NormalViewController.m
//  NotificationCenter
//
//  Copyright (c) 2014年 Y.X. All rights reserved.
//

#import "NormalViewController.h"

@interface NormalViewController ()

@end

@implementation NormalViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    // 註冊通知中心
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(notificationEvent:)
                                                 name:NSStringFromClass([self class])
                                               object:nil];
    
    // 發送消息
    [[NSNotificationCenter defaultCenter] postNotificationName:NSStringFromClass([self class])
                                                        object:nil
                                                      userInfo:@{@"name": @"YouXianMing"}];
    
    // 發送消息
    [[NSNotificationCenter defaultCenter] postNotificationName:NSStringFromClass([self class])
                                                        object:nil
                                                      userInfo:@{@"age": @"18"}];
}

- (void)notificationEvent:(id)sender
{
    NSNotification *tmp = (NSNotification *)sender;
    NSLog(@"%@", tmp.userInfo);
}

- (void)dealloc
{
    // 移除通知中心
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:NSStringFromClass([self class])
                                                  object:nil];
}

@end

沒有對象的概念(都是經過類方法展現):spa

獲取數據部分還有點詭異:設計

 

要將其修改到具有對象的概念,且使用起來更加人性化:)如下就是本人對齊進行的修改.code

NSObject+NotificationCenter.h   +   NSObject+NotificationCenter.morm

//
//  NSObject+NotificationCenter.h
//
//  http://home.cnblogs.com/u/YouXianMing/
//
//  Copyright (c) 2014年 Y.X. All rights reserved.
//

#import <Foundation/Foundation.h>

#ifndef SELF_CLASS_NAME 
#define SELF_CLASS_NAME   [self className]
#endif

@interface NSObject (NotificationCenter)

@property (nonatomic, strong) NSString   *notificationName;  // 通知中心名字

// 發送通知消息
- (void)sendMessage:(NSDictionary *)obj toName:(NSString *)name;

// 註冊通知中心
- (void)registerNotificationName:(NSString *)name selector:(SEL)selector;

// 移除通知中心
- (void)removeNotification:(NSString *)name;

// 發送消息的對象
- (id)messageObject;

// 消息名字
- (NSString *)messageName;

// 當前對象名字
+ (NSString *)ClassName;
- (NSString *)className;

@end
//
//  NSObject+NotificationCenter.m
//
//  http://home.cnblogs.com/u/YouXianMing/
//
//  Copyright (c) 2014年 Y.X. All rights reserved.
//

#import "NSObject+NotificationCenter.h"
#import <objc/runtime.h>

@implementation NSObject (NotificationCenter)

/* ================== 擴展了一個屬性 ================== */
static char notificationNameFlag;
- (void)setNotificationName:(NSString *)notificationName
{
    objc_setAssociatedObject(self, &notificationNameFlag,
                             nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    objc_setAssociatedObject(self, &notificationNameFlag,
                             notificationName,
                             OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSString *)notificationName
{
    return objc_getAssociatedObject(self, &notificationNameFlag);
}
/* ================== 擴展了一個屬性 ================== */


- (void)sendMessage:(NSDictionary *)obj toName:(NSString *)name
{
    // 發送消息
    [[NSNotificationCenter defaultCenter] postNotificationName:name
                                                        object:nil
                                                      userInfo:obj];
}

- (void)registerNotificationName:(NSString *)name selector:(SEL)selector
{
    // 若是沒有提供名字,則用這個類的名字來註冊
    if (name == nil)
    {
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:selector
                                                     name:NSStringFromClass([self class])
                                                   object:nil];
    }
    else
    {
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:selector
                                                     name:name
                                                   object:nil];
    }
}

- (void)removeNotification:(NSString *)name
{
    // 若是沒有提供名字,則用這個類的名字來移除(注意哦,此處須要與註冊處的名字一致!)
    if (name == nil)
    {
        [[NSNotificationCenter defaultCenter] removeObserver:self
                                                        name:NSStringFromClass([self class])
                                                      object:nil];
    }
    else
    {
        [[NSNotificationCenter defaultCenter] removeObserver:self
                                                        name:name
                                                      object:nil];
    }
}

+ (NSString *)ClassName
{
    // 返回類名
    return NSStringFromClass(self);
}

- (NSString *)className
{
    // 返回類名
    return NSStringFromClass([self class]);
}

- (id)messageObject
{
    // 消息實體內容
    if ([self isKindOfClass:[NSNotification class]])
    {
        NSNotification *tmp = (NSNotification *)self;
        return tmp.userInfo;
    }
    else
    {
        return nil;
    }
}

- (NSString *)messageName
{
    // 註冊消息者的名字
    if ([self isKindOfClass:[NSNotification class]])
    {
        NSNotification *tmp = (NSNotification *)self;
        return tmp.name;
    }
    else
    {
        return nil;
    }
}

@end

使用時的代碼以下:server

//
//  RootViewController.m
//  NotificationCenter
//
//  Copyright (c) 2014年 Y.X. All rights reserved.
//

#import "RootViewController.h"
#import "NSObject+NotificationCenter.h"

@interface RootViewController ()

@end

@implementation RootViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // 註冊通知中心
    [self registerNotificationName:[self className]
                          selector:@selector(notificationEvent:)];
    
    // 對象A發送通知
    [@"A" sendMessage:@{@"name": @"YouXianMing"}
               toName:[self className]];
    
    // 對象B發送通知
    [@"B" sendMessage:@{@"age": @"18"}
               toName:[self className]];
}

- (void)notificationEvent:(id)sender
{
    // 獲取到message
    id object = [sender messageObject];
    
    // 打印message
    NSLog(@"%@", object);
}

- (void)dealloc
{
    // 移除註冊的通知中心
    [self removeNotification:[self className]];
}

@end

至少,咱們減小了認知上面得差別,不須要你知道有通知中心這個東西存在了,取數據也有專門的方法直接獲取.對象

其實,我還擴展了一個NSObject的一個屬性,這個屬性就是用來標示被註冊通知中心名字的,如下展現的是高級用法.blog

建立Student的Model

//
//  Student.h
//  NotificationCenter
//
//  Copyright (c) 2014年 Y.X. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface Student : NSObject

@property (nonatomic, strong) NSString *name;

@end
//
//  Student.m
//  NotificationCenter
//
//  Copyright (c) 2014年 Y.X. All rights reserved.
//

#import "Student.h"
#import "NSObject+NotificationCenter.h"

@implementation Student

@synthesize name = _name;
- (void)setName:(NSString *)name
{
    _name = name;
    
    if (self.notificationName)
    {
        [self sendMessage:@{@"data": name} toName:self.notificationName];
    }
}
- (NSString *)name
{
    return _name;
}

@end

使用:

//
//  RootViewController.m
//  NotificationCenter
//
//  Copyright (c) 2014年 Y.X. All rights reserved.
//

#import "RootViewController.h"
#import "NSObject+NotificationCenter.h"
#import "Student.h"

@interface RootViewController ()

@end

@implementation RootViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // 註冊通知中心
    [self registerNotificationName:[self className]
                          selector:@selector(notificationEvent:)];
    

    Student *stu         = [Student new];
    stu.notificationName = [self className];
    stu.name             = @"YouXianMing";
}

- (void)notificationEvent:(id)sender
{
    // 獲取到message
    id object = [sender messageObject];
    
    // 打印message
    NSLog(@"%@", object);
}

- (void)dealloc
{
    // 移除註冊的通知中心
    [self removeNotification:[self className]];
}

@end

其實,這已經從"不記名字"的通知中心轉變成了"記名"的通知中心了,使用起來也是很是簡單的:)

相關文章
相關標籤/搜索