SwiftUI 專案怎麼開?實作教你設定畫面與啟用預覽

💬 這篇文章是我參加 2024 iThome 鐵人賽 時寫的,現在整理過後,重新放上部落格啦!
作為一個 UIKit 開發者,第一次打開 SwiftUI 的專案時,我的反應可以說是半熟悉半陌生😂。
有些結構名稱我看得懂,但用法又和以前不一樣。今天這篇,我會帶著自己的理解來整理 SwiftUI 專案的組成與邏輯,希望幫助像我一樣從 UIKit 轉來的新手,一起搞懂這個嶄新的開發世界。
SwiftUI 專案的基本結構
當我們在 Xcode 裡建立一個新的 SwiftUI 專案時,會自動生成一組預設檔案與資料夾。這些結構有些和 UIKit 相近,有些則是 SwiftUI 獨有的設計。我們就一個一個來看吧!

App.swift:整個 App 的起點
檔案名稱通常會是 [專案名]App.swift,像我現在的專案就叫 HandyInventoryApp.swift。
這個檔案是 SwiftUI 專案的入口點,裡面會實作 App 協議,並使用 @main 標示它是啟動點。簡單範例如下:
import SwiftUI
@main
struct HandyInventoryApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}這段意思是:當 App 被打開時,ContentView 是使用者看到的第一個畫面。
ContentView.swift:UI 從這裡開始寫起
接下來是最熟悉的檔案之一:ContentView.swift。
它是一個遵守 View 協議的 struct,而不是像 UIKit 那樣繼承 UIViewController。
import SwiftUI
struct ContentView: View {
var body: some View {
Text("Hello, world!")
.padding()
}
}
#Preview {
ContentView()
}有幾個重點我一開始也不太懂,後來才慢慢釐清:
View是一個協議(protocol),不是類別body是必須實作的屬性,用來定義 UI 要長怎樣some View是一種「不透明型別」(Opaque Type)
參考資料:
什麼是 some View?來聊聊不透明型別
我們看到 body 的回傳型別是 some View,這裡的 some 就是 Swift 中的不透明型別。
要簡單理解它,可以對照泛型的寫法:
func max<T>(_ x: T, _ y: T) -> T where T: Comparable這段泛型函式定義的 T 是「輸入參數必須相同類型,但在定義時不知道具體是哪個型別」,這就是泛型。
而不透明型別剛好相反:你知道會回傳某個特定型別(像是一個具體的 View),但你不需要在函式定義裡寫出來,編譯器自己知道就好。
也就是說:
- 泛型是「我不知道你是誰,但你們要一樣」
- 不透明型別是「我知道你是誰,但我不告訴別人」
我覺得這個用健達出奇蛋比喻滿有趣的:你知道裡面會有玩具,但每次是什麼不重要、開箱才知道。這種隱藏具體實作的設計讓 SwiftUI 更彈性,也更易於模組化。
有興趣深入研究的話,推薦三篇我看過很棒的資源(大推 ChaoCode):
Preview:讓畫面變化一眼看穿的工具
在 SwiftUI 專案中,畫面右側的預覽區(Canvas)非常重要。
能即時顯示 UI 更新、幫助我們微調細節,而這個預覽功能的觸發點在於檔案下方的 #Preview 區塊:
#Preview {
ContentView()
}預覽畫面不是 App 的一部分,它不會被編進去實體 App 中,只存在開發階段。
如果不小心把 Canvas 關掉了,可以透過 Xcode 右上角的按鈕再打開,或使用快捷鍵 ⌥ + ⌘ + Enter 快速切換。
為什麼 SwiftUI 要用 Struct 寫 View?
這點我剛開始滿疑惑的,因為以前 UIKit 都是用 Class,現在突然全部改用 Struct,不知道的人真的會有點卡。查了一下資料後,我找到幾個滿合理的理由:
- 更安全:Struct 是值型別,不像 Class 是參考型別,能避免記憶體錯誤或不小心改到同一份資料的狀況
- 效能較佳:Struct 沒有繼承鏈,相對輕量
- 更好追蹤資料變化:SwiftUI 偏向「功能性編程」,不鼓勵隱性狀態,Struct 更符合這種風格
- 降低記憶體洩漏風險:避免 Strong Reference Cycles 的問題
這些特性其實和 SwiftUI 整體的設計哲學非常一致。
專案裡的其他重要檔案與資料夾
除了上面提到的主程式與畫面檔案,專案裡還有幾個值得認識的元素:
Persistence.swift
這個檔案與 Core Data 有關,是建立資料儲存邏輯的地方。雖然底層還是 SQLite,但透過這個層包裝,我們可以用物件導向的方式操作資料,不用自己寫 SQL,對資料庫不熟的人也能快速上手。
Assets.xcassets
這裡是 App 所有圖片、icon、顏色資源的家。
未來如果我們要加圖、換色主題,都會透過這裡來管理,並透過 Image("xxx") 或 Color("yyy") 在畫面上呼叫出來。
Preview Content
這個資料夾不是拿來寫功能,而是專門提供預覽時的假資料。
如果我們要模擬 API 回傳的資料、假裝有某些圖片、測試不同狀態下的 UI,這裡就是幫手。它只存在於開發階段,不會進到正式版 App 中。
結構新,但其實不難懂
雖然 SwiftUI 的專案結構看起來跟 UIKit 有落差,但拆解後就會發現它其實非常直覺。進入點 App.swift、主畫面 ContentView.swift、Core Data 和資源資料夾各司其職,而且都設計得很一致。
老實說,我有種「雖然改變很多,但反而變簡單了」的感覺。明天我們將會開始認識各種 UI,讓我們繼續邊做邊學吧!
繼續看第四天 👉 SwiftUI 元件入門教學 – 文字、圖片、按鈕這樣用



