? ? ? ? 這里所說的通知不是指發給用戶看的通知消息,而是系統內部進行消息傳遞的通知。我在之前也寫過一篇文章介紹如何使用 NotificationCenter
來發送、接收通知(點擊查看)。
? ? ? ? 其實 RxSwift
也對 NotificationCenter
進行了擴展,使用起來變得十分簡潔,下面通過樣例進行演示。
一、系統通知的注冊與響應
1,監聽應用進入后臺的通知
(1)效果圖
程序編譯運行后,當按下設備的 home
鍵,程序進入后臺的同時會在控制臺中輸出相關信息。
(2)樣例代碼
程序進入后臺時除了會執行 AppDelegate.swift
里的 applicationDidEnterBackground
方法外,還會發送 UIApplicationDidEnterBackground
通知,這里我們使用 NotificationCenter
的 Rx
擴展方法來監聽這個通知。
關于 .takeUntil(self.rx.deallocated):
它的作用是保證頁面銷毀的時候自動移除通知注冊,避免內存浪費或奔潰。
import UIKit
import RxSwift
import RxCocoa
class ViewController: UIViewController {
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
// 監聽應用進入后臺通知
_ = NotificationCenter.default.rx
.notification(NSNotification.Name.UIApplicationDidEnterBackground)
.takeUntil(self.rx.deallocated) //頁面銷毀自動移除通知監聽
.subscribe(onNext: { _ in
print("程序進入到后臺了")
})
}
}
2,監聽鍵盤的通知
(1)效果圖
我們分別監聽虛擬鍵盤的打開和關閉通知,并在控制臺中輸出相關信息。
(2)樣例代碼
import UIKit
import RxSwift
import RxCocoa
class ViewController: UIViewController {
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
//添加文本輸入框
let textField = UITextField(frame: CGRect(x:20, y:100, width:200, height:30))
textField.borderStyle = UITextBorderStyle.roundedRect
textField.returnKeyType = .done
self.view.addSubview(textField)
//點擊鍵盤上的完成按鈕后,收起鍵盤
textField.rx.controlEvent(.editingDidEndOnExit)
.subscribe(onNext: { _ in
//收起鍵盤
textField.resignFirstResponder()
})
.disposed(by: disposeBag)
//監聽鍵盤彈出通知
_ = NotificationCenter.default.rx
.notification(NSNotification.Name.UIKeyboardWillShow)
.takeUntil(self.rx.deallocated) //頁面銷毀自動移除通知監聽
.subscribe(onNext: { _ in
print("鍵盤出現了")
})
//監聽鍵盤隱藏通知
_ = NotificationCenter.default.rx
.notification(NSNotification.Name.UIKeyboardWillHide)
.takeUntil(self.rx.deallocated) //頁面銷毀自動移除通知監聽
.subscribe(onNext: { _ in
print("鍵盤消失了")
})
}
}
二、自定義通知的發送與接收
1,基本介紹
通知類型其實就是一個字符串,所以我們也可以使用自己定義的通知(同時還可以傳遞用戶自定義數據)。
2,樣例演示
(1)ViewController.swift
(我們發出一個攜帶有自定義數據的通知,同時創建兩個觀察者來接收這個通知。)
import UIKit
import RxSwift
import RxCocoa
class ViewController: UIViewController {
let disposeBag = DisposeBag()
let observers = [MyObserver(name: "觀察器1"),MyObserver(name: "觀察器2")]
override func viewDidLoad() {
super.viewDidLoad()
print("發送通知")
let notificationName = Notification.Name(rawValue: "DownloadImageNotification")
NotificationCenter.default.post(name: notificationName, object: self,
userInfo: ["value1":"hangge.com", "value2" : 12345])
print("通知完畢")
}
}
(2)MyObserver.swift
(觀察者在收到通知后的執行的處理函數中,添加了個 3 秒的等待。)
import UIKit
import RxSwift
import RxCocoa
class MyObserver: NSObject {
var name:String = ""
init(name:String){
super.init()
self.name = name
// 接收通知:
let notificationName = Notification.Name(rawValue: "DownloadImageNotification")
_ = NotificationCenter.default.rx
.notification(notificationName)
.takeUntil(self.rx.deallocated) //頁面銷毀自動移除通知監聽
.subscribe(onNext: { notification in
//獲取通知數據
let userInfo = notification.userInfo as! [String: AnyObject]
let value1 = userInfo["value1"] as! String
let value2 = userInfo["value2"] as! Int
print("\(name) 獲取到通知,用戶數據是[\(value1),\(value2)]")
//等待3秒
sleep(3)
print("\(name) 執行完畢")
})
}
}
(3)運行結果如下。可以看出,通知發送后的執行是同步的,也就是說觀察者全部處理完畢后,主線程才繼續往下進行。