一个可以简单应用的通知中心
- 核心技术点就是使用了
NSMapTable和NSHashTable,据此可以使用weak的方式存储observer对象 - 当observer销毁时,无需通过
removeObserver方法移除观察者
import Foundation
class MyNotificationCenter {
// MARK: - private property
/// 存储通知名称和observer
private lazy var observerData: NSMapTable<NSString, NSHashTable<AnyObject>> = NSMapTable.init(keyOptions: [.strongMemory, .objectPersonality], valueOptions: [.strongMemory, .objectPointerPersonality])
/// 存储observer和selector
private lazy var selectors: NSMapTable<AnyObject, NSDictionary> = NSMapTable.init(keyOptions: [.weakMemory, .objectPointerPersonality], valueOptions: [.strongMemory, .objectPersonality])
private let sQueue = DispatchQueue(label: "MyNotificationCenterSerialQ")
// MARK: - public property
static let `default` = MyNotificationCenter()
// MARK: - public function
func addObserver(_ observer: AnyObject, selector: Selector, name: String) {
sQueue.async {
func addSelector() {
if var sdict = self.selectors.object(forKey: observer) as? [String: String] {
if sdict[name] == nil {
sdict[name] = NSStringFromSelector(selector)
}
self.selectors.setObject(sdict as NSDictionary, forKey: observer)
} else {
let dict = [name: NSStringFromSelector(selector)] as NSDictionary
self.selectors.setObject(dict, forKey: observer)
}
}
if let items = self.observerData.object(forKey: name as NSString) {
if !items.contains(observer) {
items.add(observer)
self.observerData.setObject(items, forKey: name as NSString)
addSelector()
}
} else {
let items = NSHashTable<AnyObject>.init(options: .weakMemory)
items.add(observer)
self.observerData.setObject(items, forKey: name as NSString)
addSelector()
}
}
}
func post(name: String) {
sQueue.sync {
guard let items = self.observerData.object(forKey: name as NSString) else {
return
}
DispatchQueue.main.async {
for item in items.allObjects {
if let selectorDict = self.selectors.object(forKey: item) as? [String: String],
let selector = selectorDict[name] {
_ = item.perform(Selector(selector))
}
}
}
}
}
// MARK: - private function
}