改善系統的通知中心設計模式
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, ¬ificationNameFlag, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC); objc_setAssociatedObject(self, ¬ificationNameFlag, notificationName, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (NSString *)notificationName { return objc_getAssociatedObject(self, ¬ificationNameFlag); } /* ================== 擴展了一個屬性 ================== */ - (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
其實,這已經從"不記名字"的通知中心轉變成了"記名"的通知中心了,使用起來也是很是簡單的:)