本篇講解swift中通知的用法
前言
通知作為傳遞事件和數(shù)據(jù)的載體幕垦,在使用中是不受限制的吼具。由于忘記移除某個(gè)通知的監(jiān)聽(tīng)赡勘,會(huì)造成很多潛在的問(wèn)題,這些問(wèn)題在測(cè)試中是很難被發(fā)現(xiàn)的楼熄。但這不是我們這篇文章探討的主題忆绰。
我曾見(jiàn)過(guò),有的團(tuán)隊(duì)為了管理通知孝赫,開(kāi)發(fā)了一個(gè)類似于NotificationManager
的類较木,所有通知的添加移除都通過(guò)這個(gè)類進(jìn)行管理,通過(guò)打印通知數(shù)組就能很清楚的看到添加了哪些通知青柄,以及這些通知被綁定在那些對(duì)象之上,這是一個(gè)很好地思路预侯。
發(fā)通知
swift中發(fā)通知的函數(shù)原型是這樣的:
open func post(name aName: NSNotification.Name, object anObject: Any?, userInfo aUserInfo: [AnyHashable : Any]? = nil)
除了name
之外致开,其他參數(shù)跟OC的沒(méi)什么區(qū)別,name
的主要作用就是作為通知的唯一標(biāo)識(shí)萎馅。在OC中双戳,這個(gè)name
是一個(gè)最普通的字符串,這就導(dǎo)致了開(kāi)發(fā)中的亂用的問(wèn)題糜芳。很多人為了管理這些通知字符串想出了很多辦法飒货,比如:
- 把這些字符串放到一個(gè)或幾個(gè)文件中
- 寫一個(gè)類根據(jù)不同功能提供不同的字符串魄衅,這個(gè)是比較推薦的寫法,也和本篇中講解的用法很像
Notification.Name
在上邊發(fā)通知的函數(shù)中塘辅,我們發(fā)現(xiàn)name
的類型是Notification.Name
,那么這個(gè)Notification.Name
是什么鬼呢晃虫?
extension NSNotification {
public struct Name : RawRepresentable, Equatable, Hashable, Comparable {
public init(_ rawValue: String)
public init(rawValue: String)
}
}
通過(guò)上邊的原型函數(shù)可以得出如下結(jié)論:
-
Name
是NSNotification
中的一個(gè)成員,類型是結(jié)構(gòu)體 - 通過(guò)一個(gè)字符串進(jìn)行初始化
可以使用下邊的代碼創(chuàng)建Notification.Name
:
let notificationName = Notification.Name(rawValue: "com.xxx")
高級(jí)用法
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
分類扣墩,通過(guò)擴(kuò)展了一個(gè)Task
這樣的結(jié)構(gòu)體哲银,把跟task相關(guān)的通知都綁定在這個(gè)Task
上,因此呻惕,在代碼中就可以這么使用:
NotificationCenter.default.post(
name: Notification.Name.Task.DidComplete,
object: strongSelf,
userInfo: [Notification.Key.Task: task]
)
Notification.Name.Task.DidComplete
表達(dá)的非常清晰荆责,一般都能知道是task請(qǐng)求完成之后的通知。
上邊的代碼中還出現(xiàn)了[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"
}
}
擴(kuò)展了Notification
,新增了一個(gè)Key
結(jié)構(gòu)體做院,這個(gè)結(jié)構(gòu)體用于取出通知中的userInfo。
總結(jié)
通知用起來(lái)還是比較簡(jiǎn)單的濒持,在實(shí)際開(kāi)發(fā)中键耕,可以參考Alamofire中的Notifications.swift
這個(gè)文件的設(shè)計(jì)就行,按照自己的業(yè)務(wù)創(chuàng)建不同的結(jié)構(gòu)體就可以了弥喉。
由于知識(shí)水平有限郁竟,如有錯(cuò)誤,還望指出