1. Notify
2. Delegation (by using protocol)
3. Callback
listen
NotificationCenter.default.addObserver(self, selector: #selector(想觸發的函式(notification:)), name: NSNotification.Name("監聽訊號名稱") , object: nil)
p.s 記得要在適當的時機(ex:viewDidDisappear)去removeObserver
post
NotificationCenter.default.post(name: Notification.Name("監聽訊號名稱"), object: nil)
viewControlle註冊監聽的名稱,而Downloader class負責抓取資料,當抓完資料,用post的方式通知viewController更新UI
class Downloader {
func fetchData(){
//Simulate fetch data and notify ViewController to update UI
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
NotificationCenter.default.post(name: Notification.Name(rawValue: "UpdateUI"), object: self, userInfo: ["action":100])
}
}
}
class TestViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
Downloader().fetchData()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(self, selector: #selector(updateUI), name: Notification.Name(rawValue: "UpdateUI"), object: nil)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self)
}
@objc func updateUI(notification: Notification) {
if let val = notification.userInfo?["action"] as? Int {
print("Update progress \(val)% ")
}
}
}
透過protocol(類似Android的interface),來讓兩個class之間能溝通
為了要讓viewController收到目前的進度(progress),所以viewController必須去實作用來溝通的protocol,
而Downloader需要有一個type為CommunicationDelegate的變數(在這邊我們命名為delegate),在更新進度的時候,需要用delegate這個變數去呼叫溝通的protocol的method( delegate?.currentProgress(progress: 100) ),這樣我們就能通知viewController目前下載的進度為100%
protocol CommunicationDelegate: class {
func currentProgress(progress: Int)
}
class Downloader {
weak var delegate: CommunicationDelegate? = nil
func fetechData() {
delegate?.currentProgress(progress: 100)
}
}
class TestViewController: UIViewController,CommunicationDelegate {
func currentProgress(progress: Int) {
print("Update progress \(progress)% ")
}
override func viewDidLoad() {
super.viewDidLoad()
let downloader = Downloader()
downloader.delegate = self
Downloader().fetechData()
}
}
透過callback,來讓兩個class之間能溝通.其運作原理很簡單,就是在viewController呼叫Downloader的fetchData function時,把一個function當作參數傳入.但實際上這個function仍在viewController內執行,而Downloader的fetchData function要通知viewController目前進度時,只需要把資料帶給傳入的參數function即可
class Downloader {
func fetechData(callback: (Int) -> ()) {
callback(100)
}
}
class TestViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
Downloader().fetechData {
(progress) -> Void in //<--- callback function的參數與回傳內容
print("Update progress \(progress)% ") //<--- callback function的內容
}
}
}