通知中心和通知

1.首先通知中心和通知是两码事.

通知中心是一个类---NSNotificationCenter,通知是另一个类---NSNotification.

NSNotification是对一个通知的描述,即一个通知应该包括哪些信息.哪些行为.

通知有三个属性

@property (readonly, copy) NSString *name;通知的名字.(放假通知)
@property (nullable, readonly, retain) id object;通知的发布者.(班主任)
@property (nullable, readonly, copy) NSDictionary *userInfo;通知的具体信息.(什么时候放假,什么时候收假,放假期间是否有作业,放假不要到河边玩)

初始化有两个方法

- (instancetype)initWithName:(NSString *)name object:(nullable id)object userInfo:(nullable NSDictionary *)userInfo NS_AVAILABLE(10_6, 4_0) NS_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;

通知有一个分类---NSNotificationCreation,用于创建通知,其实就是快速创建通知方法.

该分类有三个方法:

+ (instancetype)notificationWithName:(NSString *)aName object:(nullable id)anObject;//创建一个通知,包含通知的名称,通知的发布者
+ (instancetype)notificationWithName:(NSString *)aName object:(nullable id)anObject userInfo:(nullable NSDictionary *)aUserInfo;//创建一个通知,包含通知的名称,通知的发布者,通知的具体信息

- (instancetype)init /*NS_UNAVAILABLE*/;    /* do not invoke; not a valid initializer for this class */   该方法不可用,不能被调用,对于通知这个类来说不是一个有效的初始化方法

2.通知中心

通知中心其实就是不同对象间通信的中间人.比如有对象A,B.想要实现A,B对象间的通信,信息传递,就可以使用通知中心实现.A通过通知中心的POST方法发布通知,B通过通知中心的addObserver方法可以接收通知;

有些地方说每一个应用程序都内置了一个NSNotificationCenter对象.意思是UIApplication对象有一个NSNotificationCenter类型的属性.?然而查看UIApplication类,并没有这个属性.通过查询官方文档,可知每一个运行中的Cocoa应用程序默认有一个NSNotificationCenter对象,"Each running Cocoa program has a default notification center.";

作用范围:NSNotificationCenter只能在一个应用程序中实现消息的传递,如果希望在不同程序中实现消息传递,苹果官方建议使用---NSDistributedNotificationCenter.

"An NSNotificationCenter object can deliver notifications only within a single program. If you want to post a notification to other processes or receive notifications from other processes, use an instance of NSDistributedNotificationCenter."

3.通知中心的属性

    @package
    void * __strong _impl;
    void * __strong _callback;
    void *_pad[11];

??package的权限还是不太清楚

??这几个属性啥意思??回头查,这里不是重点

4.通知中心的方法

>1获得通知中心

+ (NSNotificationCenter *)defaultCenter;

>2.添加通知的接收者

- (void)addObserver:(id)observer selector:(SEL)aSelector name:(nullable NSString *)aName object:(nullable id)anObject;
参数含义:
observer:通知的接收者.某个通知由谁来接收(程序狗--我)
aSelector:接收者接收到通知后调用的方法(写代码);会把通知对象当参数传递
name:通知的名称.(做微信项目);如果为nil,可以接受到anObject发布的任何通知
anObject:通知的发布者.(老大);如果为nil,可以接收到任何对象的通知

如果name和anObject都为nil,observer可以接受到所有通知.

方法大意:"程序狗(我)"在接收到"老大"发布的"做微信项目"的通知后就会调用自己的"写代码"方法,

>3.通知的发布

- (void)postNotification:(NSNotification *)notification;//发布一个通知
- (void)postNotificationName:(NSString *)aName object:(nullable id)anObject; //发布一个通知,包括通知的发布者,通知的名字
- (void)postNotificationName:(NSString *)aName object:(nullable id)anObject userInfo:(nullable NSDictionary *)aUserInfo;//发布一个通知,包括通知的发布者,通知的名字,通知的具体信息

>4.移除接收者

- (void)removeObserver:(id)observer;//移除接收者,observer:要移除的接收者
- (void)removeObserver:(id)observer name:(nullable NSString *)aName object:(nullable id)anObject;//移除observer收到的关于anObject发布的名为aName的通知.

>5.添加接收者(2)

- (id <NSObject>)addObserverForName:(nullable NSString *)name object:(nullable id)obj queue:(nullable NSOperationQueue *)queue usingBlock:(void (^)(NSNotification *note))block NS_AVAILABLE(10_6, 4_0);
    // The return value is retained by the system, and should be held onto by the caller in
    // order to remove the observer with removeObserver: later, to stop observation.
参数含义:
name:通知的名字
obj:通知的发布者
queue:接收到通知后,block执行所在的队列
block:接收到通知调用的代码段

5.注意:

1>当通知的接收者被释放时,必须移除接收者(调用移除接收者方法):

- (void)removeObserver:(id)observer;
- (void)removeObserver:(id)observer name:(nullable NSString *)aName object:(nullable id)anObject;

就是说,如果接收者释放了,但是没有被移除,那么通知中心还会向接收者发送通知,这就是访问已经被释放的对象,就是野指针访问,故而在MRC机制下需要重写dealloc方法,在该方法中移除接收者.

6.一些可能会经常用到的通知

>1.UIDevice通知

UIDevice,简单地说就是用于描述当前设备的对象.通过该类可以获取当前设备的一些配置信息,比如设备的版本号,设备名称,型号,操作系统.电池状态.

UIDevice对象会不间断的发布一些通知:

UIDeviceOrientationDidChangeNotification //设备方向改变
UIDeviceBatteryStateDidChangeNotification //电池状态改变
UIDeviceBatteryLevelDidChangeNotification  // 电池电量改变
UIDeviceProximityStateDidChangeNotification // 近距离传感器,,接近某些东西的状态改变

>2.键盘的通知

UIKeyboardWillShowNotification;//键盘将要出现
UIKeyboardDidShowNotification;//键盘已经出现
UIKeyboardWillHideNotification;//键盘将要隐藏
UIKeyboardDidHideNotification;//键盘已经隐藏

UIKeyboardWillChangeFrameNotification  //键盘将要改变位置

 UIKeyboardDidChangeFrameNotification //键盘已经改变位置

键盘的通知会附带一些具体信息:userInfo

UIKeyboardFrameBeginUserInfoKey   //键盘位置改变前的frame
UIKeyboardFrameEndUserInfoKey       //键盘位置改变后的frame   
UIKeyboardAnimationDurationUserInfoKey //键盘位置改变的动画时间
UIKeyboardAnimationCurveUserInfoKey    //键盘动画执行的节奏(快慢)????
UIKeyboardIsLocalUserInfoKey 
UIKeyboardCenterBeginUserInfoKey 
UIKeyboardCenterEndUserInfoKey   
UIKeyboardBoundsUserInfoKey                 

 7.通知和代理之间的异同:

相同:

都可以实现对象间数据,消息传递,通信

不同:

代理需要告诉确定的对象发生了什么,通知不需要,一个对象发布通知,根本不用管谁会接收到这个通知.

8.示例代码

#import <Foundation/Foundation.h>
#import "Boss.h"
#import "Me.h"
#import "Boss2.h"
#import "Someone.h"
//boss(腾讯老大)的通知
static NSString *const WeChatDevelop = @"微信项目开发";
static NSString *const QQDevelop = @"QQ项目开发";
//boss2(新浪老大)的通知
static NSString *const WeiBoDevelop = @"微博项目开发";
static NSString *const SinaReaderDevelop = @"新浪读书项目开发";

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        //创建通知的发布者和接收者
        Boss *boss = [[Boss alloc]init];
        boss.name = @"腾讯";

        Boss2 *boss2 = [[Boss2 alloc]init];
        boss2.name = @"新浪";


        Me *me = [[Me alloc]init];
        me.name = @"王大锤";
        Someone *someone = [[Someone alloc]init];
        someone.name = @"二狗子";


        //1.获取通知中心
        NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];

//        逗比程序员成为通知接收者
//        我成为腾讯的扣扣项目的接收者
        [notificationCenter addObserver:me selector:@selector(writeQQ:) name:nil object:boss];
// someone成为微博项目接收者 [notificationCenter addObserver:someone selector:@selector(writeWeiBo:) name:WeiBoDevelop object:boss2]; // 2.老板发布通知 // 腾讯发布通知 [notificationCenter postNotificationName:WeChatDevelop object:boss userInfo:@{@"老板":boss.name,@"项目名称":@"微信开发"}]; [notificationCenter postNotificationName:QQDevelop object:boss userInfo:@{@"老板":boss.name,@"项目名称":@"QQ开发"}]; // 新浪发布通知 [notificationCenter postNotificationName:WeiBoDevelop object:boss2 userInfo:@{@"老板":boss.name,@"项目名称":@"微博开发"}]; [notificationCenter postNotificationName:SinaReaderDevelop object:boss2 userInfo:@{@"老板":boss.name,@"项目名称":@"新浪读书开发"}]; } return 0; }

控制台输出取决于添加接收者代码:

//        我成为腾讯的扣扣项目的接收者
        [notificationCenter addObserver:me selector:@selector(writeQQ:) name:nil object:boss];
可以接收到boss发出的所有通知
        [notificationCenter addObserver:me selector:@selector(writeQQ:) name:nil object:nil];
可以接受到boss,boss2(如果有其他对象也可以)发出的所有通知.
//        someone成为微博项目接收者
        [notificationCenter addObserver:someone selector:@selector(writeWeiBo:) name:WeiBoDevelop object:boss2];
可以接收到boss2的微博开发的通知

9.通知的本质

个人想法:

程序最底层是函数,方法(都是具有特定功能的代码段)的调用.

假设有对象A,B和通知中心;

A通过通知中心发布通知,调用post方法,意味着,将传入的参数,设置给NSNotification的属性(我猜测是不是这样),主要的用userInfo记录著需要传递的数据.那么add方法是如何将post方法中传入的数据传递给接收者呢?

原文地址:https://www.cnblogs.com/yufang/p/5204501.html