Alamofire源码解读系列(三)之通知处理(Notification)
本篇讲解swift中通知的用法
前言
通知作为传递事件和数据的载体,在使用中是不受限制的。由于忘记移除某个通知的监听,会造成很多潜在的问题,这些问题在测试中是很难被发现的。但这不是我们这篇文章探讨的主题。
我曾见过,有的团队为了管理通知,开发了一个类似于NotificationManager
的类,所有通知的添加移除都通过这个类进行管理,通过打印通知数组就能很清楚的看到添加了哪些通知,以及这些通知被绑定在那些对象之上,这是一个很好地思路。
发通知
swift中发通知的函数原型是这样的:
open func post(name aName: NSNotification.Name, object anObject: Any?, userInfo aUserInfo: [AnyHashable : Any]? = nil)
除了name
之外,其他参数跟OC的没什么区别,name
的主要作用就是作为通知的唯一标识。在OC中,这个name
是一个最普通的字符串,这就导致了开发中的乱用的问题。很多人为了管理这些通知字符串想出了很多办法,比如:
- 把这些字符串放到一个或几个文件中
- 写一个类根据不同功能提供不同的字符串,这个是比较推荐的写法,也和本篇中讲解的用法很像
Notification.Name
在上边发通知的函数中,我们发现name
的类型是Notification.Name
,那么这个Notification.Name
是什么鬼呢?
extension NSNotification {
public struct Name : RawRepresentable, Equatable, Hashable, Comparable {
public init(_ rawValue: String)
public init(rawValue: String)
}
}
通过上边的原型函数可以得出如下结论:
Name
是NSNotification
中的一个成员,类型是结构体- 通过一个字符串进行初始化
可以使用下边的代码创建Notification.Name
:
let notificationName = Notification.Name(rawValue: "com.xxx")
高级用法
extension Notification.Name {
/// Used as a namespace for all `URLSessionTask` related notifications.
public struct Task {
/// Posted when a `URLSessionTask` is resumed. The notification `object` contains the resumed `URLSessionTask`.
public static let DidResume = Notification.Name(rawValue: "org.alamofire.notification.name.task.didResume")
/// Posted when a `URLSessionTask` is suspended. The notification `object` contains the suspended `URLSessionTask`.
public static let DidSuspend = Notification.Name(rawValue: "org.alamofire.notification.name.task.didSuspend")
/// Posted when a `URLSessionTask` is cancelled. The notification `object` contains the cancelled `URLSessionTask`.
public static let DidCancel = Notification.Name(rawValue: "org.alamofire.notification.name.task.didCancel")
/// Posted when a `URLSessionTask` is completed. The notification `object` contains the completed `URLSessionTask`.
public static let DidComplete = Notification.Name(rawValue: "org.alamofire.notification.name.task.didComplete")
}
}
上边代码做的唯一一件事情就是给通知的name
分类,通过扩展了一个Task
这样的结构体,把跟task相关的通知都绑定在这个Task
上,因此,在代码中就可以这么使用:
NotificationCenter.default.post(
name: Notification.Name.Task.DidComplete,
object: strongSelf,
userInfo: [Notification.Key.Task: task]
)
Notification.Name.Task.DidComplete
表达的非常清晰,一般都能知道是task请求完成之后的通知。
上边的代码中还出现了[Notification.Key.Task: task]
这行代码,:
extension Notification {
/// Used as a namespace for all `Notification` user info dictionary keys.
public struct Key {
/// User info dictionary key representing the `URLSessionTask` associated with the notification.
public static let Task = "org.alamofire.notification.key.task"
}
}
扩展了Notification
,新增了一个Key
结构体,这个结构体用于取出通知中的userInfo。
总结
通知用起来还是比较简单的,在实际开发中,可以参考Alamofire中的Notifications.swift
这个文件的设计就行,按照自己的业务创建不同的结构体就可以了。
由于知识水平有限,如有错误,还望指出