通知中心其实是在程序内部提供了消息广播的一种机制,它容许咱们在低程度耦合的状况下,知足控制器与一个任意的对象进行通讯的目的。每个 iOS 程序(即每个进程)都有一个本身的通知中心,即 NSNotificationCenter 对象,该对象采用单例设计模式,能够经过类方法 defaultCenter 得到当前进程惟一的通知中心对象。一个 NSNotificationCenter 能够有许多的通知消息 NSNotification,对于每个 NSNotification 能够有不少的观察者 Observer 来接收通知。NSNotificationCenter 是 iOS 中通知中心的灵魂,由该类实现了观察者模式,并给开发者提供了诸如注册、删除观察者的接口。设计模式
通知中心以同步的方法将消息转发到全部的观察者中,换言之 NSNotificationCenter 在发送消息后,会一直等待被调用的方法执行完毕,而后返回控制权到主函数中,再接着执行后面的功能,即这是一个同步阻塞的操做。若是咱们须要异步的处理消息,直接返回控制权,则应该使用通知队列 NSNotificationQueue,在子线程中将通知加入到通知队列中,在多线程程序中,通知会被分发到每个发送消息的线程中,这可能与观察者注册时所在的线程已经不是同一个线程。多线程
任何一个对象均可以向通知中心发布通知(NSNotification),描述本身在作什么。其余感兴趣的对象(Observer)能够申请在某个特定通知发布时(或在某个特定的对象发布通知时)收到这个通知。异步
使用 [NSNotificationCenter defaultCenter] 发送的通知不管是在主线程仍是子线程中被注册,观察者注册的选择器方法都会在主线程中被执行。执行顺序为:main runloop -> 发送通知 -> 观察者选 择器方法(按照观察者注册的顺序执行)-> 通知发送者方法中其它的操做 -> main runloop。async
在子线程中使用 [NSNotificationQueue defaultQueue] 将通知加入到通知队列中,观察者选择器方法就会在子线程中被执行。子线程执行顺序为:发送通知 -> 观察者选择器方法(按照观察者注册的顺序同 步执行)-> 通知发送者方法中其它的操做。ide
若是要在同一台机器上进行进程间的通讯,须要使用 NSDistributedNOtificationCenter。函数
优点:oop
缺点:post
目的:动画
方式:ui
通知和代理的区别:
通知中心是同步的,仍是异步的 ?
系统发送 Notification,用户不须要手动发送通知,设置的事件触发时,系统自动发送通知。
通知中心不会保留(retain)监听器对象,在通知中心注册过的对象,必须在该对象释放前取消注册。不然,当相应的通知再次出现时,通知中心仍然会向该监听器发送消息。由于相应的监听器对象已经被释放了,因此可能会致使应用崩溃。通常在监听器销毁以前取消注册(如在监听器中加入下列代码):
- (void)dealloc { // [super dealloc]; // 非 ARC 中须要调用此句 [[NSNotificationCenter defaultCenter] removeObserver:self]; }
在注册、移除通知时,通知名称标示(aName)使用系统定义的标示。
注册通知(观察者)
Objective-C
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playFinished) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
Swift
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ViewController.playFinished), name:AVPlayerItemDidPlayToEndTimeNotification, object: nil)
移除通知(观察者)
Objective-C
[[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
Swift
NSNotificationCenter.defaultCenter().removeObserver(self, name:AVPlayerItemDidPlayToEndTimeNotification, object:nil)
使用 [NSNotificationCenter defaultCenter] 发送的通知不管是在主线程仍是子线程中被注册,观察者注册的选择器方法都会在主线程中被执行。
执行顺序:main runloop -> 发送通知 -> 观察者选择器方法(按照观察者注册的顺序执行)-> 通知发送者方法中其它的操做 -> main runloop
通知(消息)的建立
+ (instancetype)notificationWithName:(NSString *)aName object:(nullable id)anObject; + (instancetype)notificationWithName:(NSString *)aName object:(nullable id)anObject userInfo:(nullable NSDictionary *)aUserInfo; public convenience init(name aName: String, object anObject: AnyObject?) public init(name: String, object: AnyObject?, userInfo: [NSObject : AnyObject]?) 参数说明: aName :通知名称 anObject :传递给观察者的任意对象,通知发布者(是谁要发布通知) aUserInfo:传递的消息内容,自定义字典,能够传递更多附加信息,一些额外的信息(通知发布者传递给通知接收者的信息内容)
Objective-C
// 不带消息内容 NSNotification *notification1 = [NSNotification notificationWithName:@"notification1" object:self]; // 带消息内容 NSNotification *notification2 = [NSNotification notificationWithName:@"notification2" object:self userInfo:@{@"name":_name, @"age":_age}];
Swift
// 不带消息内容 let notification1 = NSNotification(name: "notification1", object: self) // 带消息内容 let notification2 = NSNotification(name: "notification2", object: self, userInfo: ["name":name, "age":age])
发送通知
- (void)postNotification:(NSNotification *)notification; - (void)postNotificationName:(NSString *)aName object:(nullable id)anObject; - (void)postNotificationName:(NSString *)aName object:(nullable id)anObject userInfo:(nullable NSDictionary *)aUserInfo; public func postNotification(notification: NSNotification) public func postNotificationName(aName: String, object anObject: AnyObject?) public func postNotificationName(aName: String, object anObject: AnyObject?, userInfo aUserInfo: [NSObject : AnyObject]?) 参数说明: notification:发送的通知(消息) aName :通知名称 anObject :传递给观察者的任意对象,通知发布者 aUserInfo :传递的消息内容,自定义字典,能够传递更多附加信息
Objective-C
// 发送建立好的消息 [[NSNotificationCenter defaultCenter] postNotification:notification1]; // 直接发送消息,不带消息内容 [[NSNotificationCenter defaultCenter] postNotificationName:@"notification3" object:self]; // 直接发送消息,带消息内容 [[NSNotificationCenter defaultCenter] postNotificationName:@"notification4" object:self userInfo:@{@"name":_name, @"age":_age}];
Swift
// 发送建立好的消息 NSNotificationCenter.defaultCenter().postNotification(notification1) // 直接发送消息,不带消息内容 NSNotificationCenter.defaultCenter().postNotificationName("notification3", object: self) // 直接发送消息,带消息内容 NSNotificationCenter.defaultCenter().postNotificationName("notification4", object: self, userInfo: ["name":name, "age":age])
注册通知(观察者)
- (void)addObserver:(id)observer selector:(SEL)aSelector name:(nullable NSString *)aName object:(nullable id)anObject; public func addObserver(observer: AnyObject, selector aSelector: Selector, name aName: String?, object anObject: AnyObject?) 参数说明: observer :观察者,即谁要接收这个通知; aSelector:收到通知后调用何种方法,即回调函数,而且把通知对象当作参数传入; aName :通知的名字,也是通知的惟一标示,编译器就经过这个找到通知的。 为 nil 时,表示注册全部通知,那么不管通知的名称是什么,监听器都能收到这个通知; anObject :通知发送者,为 nil 时,表示监听全部发送者的通知。若是 anObject 和 aName 都为 nil,监听器都收到全部的通知。 - (id)addObserverForName:(NSString *)name object:(id)obj queue:(NSOperationQueue *)queue usingBlock:(void (^)(NSNotification *note))block; 参数说明: name :通知的名称 obj :通知发布者 queue:决定了 block 在哪一个操做队列中执行,若是传 nil,默认在当前操做队列中同步执行 block:收到对应的通知时,会回调这个 block
Objective-C
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notification1Sel) name:@"notification1" object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notification2Sel:) name:@"notification2" object:nil]; // 通知触发方法,通知无内容 - (void)notification1Sel { } // 通知触发方法,通知有内容 - (void)notification2Sel:(NSNotification *)notification { // 接收用户消息内容 NSDictionary *userInfo = notification.userInfo; }
Swift
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ViewController.notification1Sel), name: "notification1", object: nil) NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ViewController.notification2Sel(_:)), name: "notification2", object: nil) // 通知触发方法,通知无内容 func notification1Sel() { } // 通知触发方法,通知有内容 func notification2Sel(notification:NSNotification) { // 接收用户消息内容 let userInfo = notification.userInfo }
移除通知(观察者)
- (void)removeObserver:(id)observer; - (void)removeObserver:(id)observer name:(nullable NSString *)aName object:(nullable id)anObject; public func removeObserver(observer: AnyObject) public func removeObserver(observer: AnyObject, name aName: String?, object anObject: AnyObject?) 参数说明: observer:观察者,即在什么地方接收通知; aName :通知的名字,也是通知的惟一标示,编译器就经过这个找到通知的。 anObject:通知发送者,为 nil 时,表示移除知足条件的全部发送者的通知。
Objective-C
// 移除此观察者的全部通知 [[NSNotificationCenter defaultCenter] removeObserver:self]; // 移除指定名字的通知 [[NSNotificationCenter defaultCenter] removeObserver:self name:@"notification1" object:nil];
Swift
// 移除此观察者的全部通知 NSNotificationCenter.defaultCenter().removeObserver(self) // 移除指定名字的通知 NSNotificationCenter.defaultCenter().removeObserver(self, name:"notification1", object:nil)
在子线程中使用 [NSNotificationQueue defaultQueue] 将通知加入到通知队列中,观察者选择器方法就会在子线程中被执行。
| -> -> -> -> -> -> -> -> main runloop -> -> -> -> -> -> -> -> -> -> | 执行顺序:main runloop -> | | -> main runloop | -> 发送通知 -> 观察者选择器方法(按照观察者注册的顺序同步执行)-> 通知发送者方法中其它的操做 |
发送异步通知
- (void)enqueueNotification:(NSNotification *)notification postingStyle:(NSPostingStyle)postingStyle; - (void)enqueueNotification:(NSNotification *)notification postingStyle:(NSPostingStyle)postingStyle coalesceMask:(NSNotificationCoalescing)coalesceMask forModes:(nullable NSArray<NSString *> *)modes; 参数说明: notification:通知 postingStyle:发布方式 coalesceMask:合并方式 modes :运行循环模式,nil 表示 NSDefaultRunLoopMode NSPostingStyle :发布方式 NSPostWhenIdle = 1, :空闲时发布 NSPostASAP = 2, :尽快发布 NSPostNow = 3 :当即发布 NSNotificationCoalescing :合并方式 NSNotificationNoCoalescing = 0, :不合并 NSNotificationCoalescingOnName = 1, :按名称合并 NSNotificationCoalescingOnSender = 2 :按发布者合并
Objective-C
// 建立通知 NSNotification *asyncNotification = [NSNotification notificationWithName:@"asyncNotification" object:self]; dispatch_async(dispatch_get_global_queue(0, 0), ^{ // 将通知添加到发送队列中,发送通知 [[NSNotificationQueue defaultQueue] enqueueNotification:asyncNotification postingStyle:NSPostWhenIdle]; });
移除异步通知
- (void)dequeueNotificationsMatching:(NSNotification *)notification coalesceMask:(NSUInteger)coalesceMask; 参数说明: notification:通知 coalesceMask:合并方式
Objective-C
// 移除通知,不是当即发布的通知能够被移除 [[NSNotificationQueue defaultQueue] dequeueNotificationsMatching:asyncNotification coalesceMask:0];
UIDevice 类提供了一个单例对象,它表明着设备,经过它能够得到一些设备相关的信息,好比电池电量值(batteryLevel)、电池状态(batteryState)、设备的类型(model,好比 iPod、iPhone 等)、设备的系统(systemVersion)。经过 [UIDevice currentDevice] 能够获取这个单例对象。
UIDevice 对象会不间断地发布一些通知,下列是 UIDevice 对象所发布通知的名称常量:
UIDeviceOrientationDidChangeNotification // 设备旋转 UIDeviceBatteryStateDidChangeNotification // 电池状态改变 UIDeviceBatteryLevelDidChangeNotification // 电池电量改变 UIDeviceProximityStateDidChangeNotification // 近距离传感器(好比设备贴近了使用者的脸部)
咱们常常须要在键盘弹出或者隐藏的时候作一些特定的操做,所以须要监听键盘的状态。
键盘状态改变的时候,系统会发出一些特定的通知:
UIKeyboardWillShowNotification // 键盘即将显示 UIKeyboardDidShowNotification // 键盘显示完毕 UIKeyboardWillHideNotification // 键盘即将隐藏 UIKeyboardDidHideNotification // 键盘隐藏完毕 UIKeyboardWillChangeFrameNotification // 键盘的位置尺寸即将发生改变 UIKeyboardDidChangeFrameNotification // 键盘的位置尺寸改变完毕
系统发出键盘通知时,会附带一下跟键盘有关的额外信息(字典),字典常见的 key 以下:
UIKeyboardFrameBeginUserInfoKey // 键盘刚开始的 frame UIKeyboardFrameEndUserInfoKey // 键盘最终的 frame(动画执行完毕后) UIKeyboardAnimationDurationUserInfoKey // 键盘动画的时间 UIKeyboardAnimationCurveUserInfoKey // 键盘动画的执行节奏(快慢)