SwiftUI 與 Combine(簡介)

什麼是SwiftUI?

蘋果開發平臺的新UI框架,基於swift。由於swift ABI 穩定,將會誕生更多的swift框架。SwiftUI是用來替換原IOS平臺的UIKit和macOS的APPKit的UI框架,特性是聲明式的編程。

什麼是Combine?

Combine框架爲你的應用程序處理事件提供了一種聲明性的方法。你可以爲給定的事件源創建單個處理鏈,而不是潛在地實現多個委託回調或完成處理程序閉包。鏈的每個部分都是一個合併運算符,對從上一步接收到的元素執行不同的操作。(類似於RXSwift中的Observable和各種操作符)

響應式編程:

對於蘋果的平臺,已經有幾個第三方響應式框架,比如RxSwift,它實現了Rx標準;ReactiveSwift,它受到了Rx的啓發;intercellar,它是一個自定義實現。
Combine實現了一個與Rx不同但類似的標準,稱爲響應流。響應流與Rx有一些關鍵的區別,但它們都有着大多數相同的核心概念。
如果您以前沒有使用過上面提到的一個或另一個框架,請不要擔心。到目前爲止,反應式編程已經成爲蘋果平臺的一個相當小的概念,特別是在Swift中
如果你之前有RXSwift或者ReactiveCocoa的響應式編程經驗,你將很容易學習SwiftUI+Combine編程。如果沒有這部分知識,沒有關係,並且你可以忽略以下文章中所有關於RXSwift的內容,但你需要了解這將是一種和原本UIKIt和AppKit都不同的UI編程方式,原本的UIKit更新界面操作的是UI組件對象的屬性,而新的編程方式則是將數據和UI進行綁定,需要更改UI界面時,直接修改數據源或者頁面狀態,而UI頁面將自動過渡到新的狀態。

異步編程:

原本的Foundation+UIKIt/AppKit通過通知、代理、閉包和GCD等提供了豐富的異步編程方式,這些處理方式在過去一直服務於蘋果應用開發,在SwiftUI早期我們仍然可能會用到這部分內容,但是SwiftUI+Combine也提供了其獨有的異步處理事件方式

Combine旨在向Swift生態系統引入一種新的語言,幫助您在異步編程世界的混亂中帶來更多的秩序。蘋果已經將Combine的API深深地集成到了基礎框架中,因此Timer、NotificationCenter和核心框架(比如CoreData)已經在使用它的語言。幸運的是,Combine也很容易集成到您自己的代碼中。
爲了讓您瞭解Apple如何致力於使用Combine進行響應式編程,這裏有一個簡單的圖表,顯示了Combine在系統層次結構中的位置:



各種系統框架,從Foundation一直到SwiftUI,都依賴於Combine,並提供Combine集成作爲其“傳統”api的替代。
因爲Combine是一個Apple框架,所以它並不是要取消經過良好測試的、可靠的api(如Timer或NotificationCenter)的角色。這些基礎類型仍然存在,並盡了自己的職責。相反,Combine與它們集成,並允許應用程序中的所有類型通過一種新的通用語言彼此異步對話。
因此如果理想的話我們可以使用同一種異步工具鏈接應用的各個部分 ,從數據模型到網絡層直至用戶界面。

何時可以使用新的框架

在iOS 13/macOS Catalina中,蘋果通過內置的系統框架Combine爲其生態系統帶來了響應式編程支持。
與蘋果的任何新技術一樣(比如當初的Swift),它的應用程序起初都有點有限:您只能將Combine用於支持iOS 13/macOS Catalina或更高版本的應用程序。但與蘋果押注的任何技術一樣,它的支持將迅速普及,對Combine編程的技能需求將激增。
話雖如此,從學習Combine的一些基本知識開始,看看它如何幫助您編寫安全可靠的異步代碼。

Combine基礎

簡單來說Combine編程具有三個重要成員:publishers、operators、subscribers,我們將在之後慢慢介紹着三大成員以及適用於這些成員的操作符。

Publishers

publishers可以隨時間推移向一個或多個訂閱者(如subscribers)發送值類型數據。不管Publisher的內部邏輯(幾乎可以是任何東西,包括數學計算、聯網或處理用戶事件),每個Publisher都可以發出這三種類型的多個事件:

  1. 泛型類型的值(類似RXSwift的next事件)。

  2. successful completion完成事件。(類似RXSwift的complete事件)

  3. error completion 錯誤事件。(類似RXSwift的error事件)

一個publisher 可以發出零個或多個值,如果發出success或者error事件這不再發出更多值

下面是發佈Int值的Publisher在時間線上的可視化效果:


publishers也內置了錯誤處理,因此如果你需要的話,你也可以自定義錯誤處理。
Publisher協議有兩個泛型類型,從上圖中可以看出:
•Publisher.Output是Publisher的輸出值類型。如果publisher專門化爲Int,則它永遠不會發出字符串或日期值。
•Publisher.Failure是publisher在失敗時可能引發的錯誤類型。如果發佈服務器永遠不會失敗,則可以使用Never來指定。
當您訂閱一個給定的Publisher時,你知道期望從它獲得什麼類型的值,以及它可能會失敗的錯誤。

Operators

操作符是在Publisher協議上聲明的方法,返回相同或新的Publisher。(類似於Swift標準庫中數組的操作符map、filter、zip等的作用,RXSwift中也是類似的)
操作符是高度耦合和可組合的,當一個操作符的輸出試下一個操作符的輸入時你可以想拼圖一樣將他們組裝在一起,的到想要的值


用明確的聲明式方法定義每個處理過程,你可以確定每個處理的順序,以及得到正確的輸入輸出值類型

Subscribers

最後,你到達訂閱鏈的末端:每個訂閱鏈都以Subscriber結束,來對Publisher發出的輸出或完成事件執行“操作”。


目前,Combine提供了兩個內置的subscriber,這使得處理數據流變得簡單

  • sink subscriber 允許您提供閉包和接收值和完成事件。你可以訂閱到任何發出的事件。
  • assign subscriber允許您在不需要自定義代碼的情況下,將結果輸出綁定到數據模型或UI控件上的某個屬性,以便通過key Path直接在屏幕上顯示數據。

如果您對數據有其他需求,創建自定義Subscriber甚至比創建Publisher更容易。Combine使用一組非常簡單的協議,允許您構建自己的自定義工具。

Subscriptions

當您在訂閱鏈的末尾添加subscriber時,它會在鏈的開頭一直“激活”publisher。這是一個需要記住的奇怪但重要的細節-如果沒有subscriber潛在地接收輸出,則publisher不會發出任何值。
一旦訂閱代碼編譯成功,並且自定義代碼中沒有邏輯問題,就完成了!按照設計,每當某個事件(如用戶手勢、計時器關閉或其他事件)喚醒某個publisher時,訂閱將異步“啓動”。
更好的是,由於Combine提供了一個稱爲Cancellable的協議,您不需要專門管理內存訂閱。

兩個系統提供的subscriber都符合Cancellable協議的,這意味着您的訂閱代碼(例如,整個publisher、operator和subscriber調用鏈)返回一個可取消的對象。每當您從內存中釋放該對象時,它將取消整個訂閱並從內存中釋放其資源。(作用類似RXSwift DisposeBag)

例如,這意味着您可以通過將訂閱存儲在視圖控制器上的屬性中,輕鬆地管理“綁定”訂閱的生命週期。這樣,每當用戶從視圖堆棧中解除視圖控制器時,將釋放屬性,同時也將取消您的訂閱。

應用程序架構

可能碰到這個問題時那你會說這超出了你學習的預期值,但是不要擔心,Combine不是一個影響應用程序結構的框架,你可以在MVC(Model-View-Controller)應用程序中使用Combine,也可以在MVVM(Model-View-ViewModel)代碼、VIPER等中使用Combine。您可以迭代和有選擇地添加Combine代碼,只在希望在代碼庫中改進的部分使用它。這不是一個“要麼全有要麼全無”的選擇。
如果你同時採用Combine和SwiftUI,情況就稍微不同了。在這種情況下,將C從MVC架構中刪除確實是有意義的。但這要歸功於Combine和SwiftUI的協同使用——這兩種物資在同一個房間裏都會發生反應。
你不再需要Viewcontroller去控制你的視圖顯示,當你的到數據後這一切都交給SwiftUI和Combine處理就行了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章