Swift — 玩玩 Publishers & Subscribers
讓我們使用 Publishers 和 Subscribers 來實作訂閱關係吧!
✒︎ 前言:
前面寫了許多關於 Combine 在官方文件中的成員描述以及使用方法,然後這次讓我們來實際玩玩其中的成員來製作一些簡單的應用吧!
如果還沒看過前幾篇 Combine 在官方文件中的介紹,也可以先閱讀我以下的幾篇簡單的介紹文章:
✒︎ 目錄
- Publisher & Subscriber 流程
- 實作應用介紹
- 實作訂閱關係
✒︎ Publisher & Subscriber 流程
首先,在實作之前。我們先來了解 Combine 中 Publisher
以及 Subscriber
間的訂閱以及傳遞的流程,如下圖:
基本上就是 Subscriber
會訂閱(附加 or 連接)在一個 Publisher
,而這時 Publisher
會返回一個 Subscription 也就是所謂的訂閱,我們會藉由這個訂閱來保持兩者間的訂閱關係,我們也可以藉由移除它或是主動調用 cancel()
來取消訂閱關係。一旦有了這個訂閱關係後,Subscriber
會向 Publisher
要求值,而 Publisher
會向 Subscriber
發送值以及發送完成或是錯誤。
✒︎ 實作應用介紹:
首先,我們來實作一個簡單的應用,一個單純把 TextFiled 中的 text 內容在其上方的 Label 中顯示:
在我們不用任何框架的情況,最單純的方式應該是透過 didSet
來實現:
接著讓我們看看如何使用 Combine 提供的內容來達成一樣的效果吧!
✒︎ 實作訂閱關係:
為了方便管理以及存儲的訂閱關係,首先我們在 ViewController
中宣告一個存儲訂閱的 Set
,其類型為 Set<AnyCancellable>
:
private var subscriptions: Set<AnyCancellable> = []
1. 標記 @Published:
首先,第一種方式是使用 @Published
這個 property wrapper 來標記這個 username
屬性,而之後我們透過 $
符號來訪問其中的 Publisher
:
接著我們可以簡單的透過 sink
或是 assign
的方式來創建訂閱關係:
比較特別的是 assign(to:on:)
這個方式,透過這個方式我們可直接把值透過 keyPath 的方式分配物件的特定內容中,而不是類似於 sink
的閉包方式。如此一來也可以省略掉需要處理捕獲值 weak
或是 unowned
的狀況。
2. 透過 Subject 傳遞
接著我們換成以 Subject
方式來處理。首先我們使用 PassthroughSubject
來處理,而因為 Subject
也是一種 Publisher
,所以我們一樣可以使用 sink
或 assign
的方式創建訂閱。接著使用 Subject
中send
方法來發布值:
接著我們使用另一個 Subject
,叫做 CurrentValueSubject
。我們可以透過更改該 subject
中的 value
來發布值,或是一樣透過 send
方法來發布值。
在這兩個 Subject
中我們將其泛型定義為 <String?, Never>
,前面的表示傳遞的類型,而後面的是指錯誤的類型,在這邊因為我們不會有任何錯誤,所以可以使用 Never
。
3. 透過 NotificationCenter.Publisher
這邊我們也可以使用 NotificationCenter
的 Publisher
,我們將它用於 UITextField.textDidChangeNotification
事件中,並且將 object
設置為 usernameTextField
,接著我們透過幾個 operator 將 notification
轉換為 String?
,並且一樣透過 assign
方法分配給 usernameLabel
的 text
:
透過這一連串的程式碼後,我們就創建完成 Publisher
以及 Subscriber
,並且連接完成其訂閱關係了。
✒︎ 後記:
最近因為 Combine 的問世,強迫自己學習一些當前熱門的技術,而確實 Combine 的出現對於我編寫程式碼的概念也有了一個重大的改變,最近也一直不斷的在研讀 MVVM 相關的文章,希望自己之後能配合 Combine 寫出一個完美的架構。而有關於 Combine 更清楚或詳細的介紹,這邊推薦可以去看 WWDC 中介紹 Combine 的幾個片段,可以更了解他的流程以及強大。