[SwiftUI] 初探 View protocol

SC Tuan
3 min readJun 23, 2022

--

一年前寫的,居然沒發出去,現在補發,不過看著看著又陌生了起來。

寫了一些範例之後,我還是不知道那最基本的 View protocol 裡面是什麼意思,可能太久沒寫了,這一篇花一點時間搞懂他到底做了什麼事情。

以下內容是 Xcode 11.7, Swift 5 的原始碼。

先看 Protocol 宣告

public protocol View {    associatedtype Body : View    var body: Self.Body { get }}

一個一個看吧。

如同 generic 的代號

我自己理解的,associatedtype 就是儲存了到時遵守這個協議的類別名稱的類別變數。然後這裡的宣告又清楚指明了該類別必然是遵守 View 協議的。

簡單來說,如果你實作一個 SwiftUI 類別如下:

struct ContentView: View {}

那麼, Body 就代表了 ContentView 這個類別。

類別也有 Self 可用

而首字母大寫的 Self 呢?其實就是相當於物件實例的 self ,所以後面宣告 body 這個 computed property 的內容就告訴你, Body 就是類別級別的 property 了,而他的命名規則也遵守「類別的首字母會大寫」的通用規則,種種跡象告訴你, Body 就是類別。

所以,同上面的案例,其實遵守 View 的類別實作的 body ,應該會是如下:

struct ContentView: View {    var body: ContentView {    }}

但如果你真的這樣做,你跑起來會遇到一個錯誤:

Cannot convert return expression of type 'some View' to return type 'ContentView'

修復方式是把你實作在 body 裡面的物件轉換成 ContentView

不想這麼麻煩,some 關鍵字

先聲明一下,下面的內容其實真的只能當作參考,讀完 opaque type 後我發現要講的太多了,但不想要把這篇寫得更長了。

於是你通常會看到大家不會這樣寫 body 的實作,通常會這樣寫:

struct ContentView: View {    var body: some View {    }}

所以你可以猜測這個關鍵字的意思了,是的,就像你讀英文小說時,遇到不會的單字就從上下文去猜他的意思, some 應該是代表了他的回傳值是一個類似 View 的東西,不管他到底是什麼,該類別/struct/whatever…遵守 View 協議就對了 (後面讀了一些資料,我發現這樣講並不好,因為聽起來好像是 protocol type,但其實不是,因為他其實是指到一個具體的 type ,只是你不知道是什麼而已,所以這個用法比起光用 protocol ,更加強調了 type 的重要性)。

雖然看起來很像是 protocol 的寫法,但其實這是 opaque type ,簡單說就是把類別的複雜度隱藏在函數實作的邏輯裡面,在這邊也就是說, body 裡面怎樣去結合出畫面的,到底是用了多少 TextZStack 之類的元件我都不管,我去呼叫 body 的人,只在乎回傳的結果而已。

寫到這裡,我只是想做個結尾,詳情請見 opaque type ,已列在下面可以去看一看喔。

參考

--

--

SC Tuan
SC Tuan

Written by SC Tuan

iOS developer(Obj-C & Swift) / Web developer (Java, Javascript, CSS,HTML)

No responses yet