IOS学习笔记: Notifications
本人IOS小白一枚,如理解有误,请各位大神补充/斧正
基本概念
什么是Notification? 英语八级的你一定知道这是通知的意思,那什么是通知呢?
概念上,IOS的通知机制,允许一个对象通过“广播通知”的方式,告知其他的对象(通知的监听者)“有事情发生了!!!”,这些监听者在接收到通知以后,可以做出相应的处理。
从这段鄙人很不专业的描述中可以看出:
1. 通知机制可以实现由一个对象负责监听事件,由其他若干对象来负责事件的具体处理。(分工,降低单个对象复杂度)
2. 通知的发送者,发送了通知A,但不知道谁会监听到通知,也不知道会被如何处理; 通知的接受者,只知道接收到通知A,也知道自己要怎么处理这个通知,但是不知道是谁发送的通知。(模块独立性)
备注: 本文讨论的是Notification,是对象之间的一种交流机制,而不是UserNotification(设置推送) , 注意区别!
实现方法:
要实现通知的功能,至少要有以下几个要素:
1. 通知: Notification
2. 通知发送者: 将通知放到通知中转站上
3. 通知中转站: NotificationCenter
4. 通知监听者: observer
这样讲还是比较模糊,也说不清楚,举一个小栗子吧!
很多人都坐过灰机,知道下灰机之后第一件事情就是取行李(shang’ce’suo),那么我们就以取行李为例吧!
我们先来捋一捋机场取行李的过程:
1. 机场工作人员拿起一个行李,贴上唯一的身份码,把行李放到传送带上
2. 我在传送带旁边等待自己的行李
3. 乘客 一旦发现自己的行李(身份码与自己手中条子上的一样),执行相应的操作( 取行李)
在这个过程中不同的对象分别充当了一下角色:
- 行李: 通知(Notification)
- 唯一身份码: 通知名称(必须唯一,用于识别不同的通知)
- 传送带工作人员: 通知发送者(负责post Notification)
- 行李传送带: 通知中转站(NotificationCenter)
- 乘客: 通知监听者(observer)
代码实现:
接下来我们把取行李这个过程用代码来模拟一下,具体看看通知机制的代码实现
如图,先创建两个swift文件,分别命名为Passager.swift和AirportStaff.swift,分别代表乘客和机组成员两个类。
备注:以下是代码展示,后面将对一些代码细节进行回顾。
Passager.swift中
import Foundation
import UIKit
//定义乘客类
class Passager {
//乘客名字
let name: String
init(name: String) {
self.name = name
}
func waittingForLuggage(_ luggageName: Notification.Name) {
//将对象注册成为名为Notification.Name的通知的observer,监听该通知
NotificationCenter.default.addObserver(forName: luggageName, object: nil, queue: OperationQueue.main) {
_ in
//如果接收到通知,输出信息
print("\(self.name): Get my luggage")
}
}
}
AirportStaff.swift中
import Foundation
import UIKit
class AirportStaff {
func postLuggage(_ name: Notification.Name) {
print("airportStaff: I put \(name.rawValue) on the Conveyor")
//创建一个名为name的通知,放入NotificationCenter
NotificationCenter.default.post(name: name, object: nil)
}
}
最后,在AppDelegate.swift文件的
application(_ didFinishLaunchingWithOptions launchOptions: )函数中进行测试
先在class外面定义两个全局变量:
//创建和接收通知都需要通过唯一的通知名,因此首先定义两个通知名
let xiaomingLuggage = Notification.Name(rawValue: "XiaoMingLuggage")
let laowangLuggage = Notification.Name(rawValue: "LaoWangLuggage")
然后,修改AppDelegate.swift文件中的
application(_ didFinishLaunchingWithOptions launchOptions: )函数为:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
//1. 创建三个对象: 机组人员(发送者),乘客小明和乘客老王(observer)
let airPortStaff = AirportStaff()
let xiaoMing = Passager(name: "XiaoMing")
let laoWang = Passager(name: "LaoWan")
//2. 小明和老王分别等待各自的行李(注册小明和老王两个对象为observer,等待通知)
//现在,这两个对象都在监听Notification上的通知
xiaoMing.waittingForLuggage(xiaomingLuggage)
laoWang.waittingForLuggage(laowangLuggage)
//3. 机组人员将小明的行李放上传送带
//两个人都能看到,但是只有小明做出反应
airPortStaff.postLuggage(xiaomingLuggage)
//4. 机组人员将老王的行李放上传送带
//两个人都能看到,但是只有老王做出反应
airPortStaff.postLuggage(laowangLuggage)
return true
}
测试输出:
airportStaff: I put XiaoMingLuggage on the Conveyor
XiaoMing: Get my luggage
airportStaff: I put LaoWangLuggage on the Conveyor
LaoWan: Get my luggage
从输出中可以看到,当发送通知“xiaomingLuggage”,只有小明做出了反应,因为小明是通知“xiaomingLuggage”的唯一监听者; 相应地,当发送通知“laowangLuggage”,只有老王做出了反应,因为老王是通知“laowangLuggage”的唯一监听者
代码细节回顾:
以下代码将当前对象(方法的调用者)注册为默认NotificationCenter的监听者(observer),并指定当前对象监听名为luggageName的通知
NotificationCenter.default.addObserver(forName: luggageName, object: nil, queue: OperationQueue.main)
1) NotificationCenter: 是一个类,可以理解为是“通知的中转站”或者“通知展示区”,发送者将通知发送到上面,而监听者监听上面的通知,等待自己想要的通知
2)default变量:是NotificationCenter类的一个类变量。.default代表使用默认的NotificationCenter。当然也可以不使用默认的NotificationCenter,而选择创建自己的NotificationCenter这里不做赘述。
3)调用addObserver(forName:object:queue:using:)方法,注册当前对象为NotificationCenter的监听者()
- forName: 接受一个Notification.Name类型的参数,表示通知的名称(必须是唯一的),用于指定要监听哪一个通知。
- object: 接受一个对象(泛类型),表示只接收指定对象的通知。值为nil代表不指定特定的对象
- queue: 接受一个队列,协调多线程操作。程序中的QueueOperation.main表示多线程
- using: 接受一个closure,指定接收到通知后要执行的操作
4)建立并初始化“通知名称”对象:
Notification.Name(rawValue: String)