【SwiftUI】enumと@ViewBuilderを使ってTabViewの可読性を向上させる方法
はじめに
TabViewをいい感じ(可読性と拡張性)を向上させる方法を扱います。
今回、扱うキーワードは、
TabView
enum
@ViewBuilder
です。
TabViewの例(Apple Developer documentationから引用):
環境
- OS:macOS Sonoma 14.2
- Xcode:15.1 (15C65)
- Swift:5.9.2
既存のコードをリファクタリングする
サンプルとして、TabViewを実装している次のようなContentViewをリファクタリングしていきます。
struct ContentView: View {
@State private var selectedTab = 0
var body: some View {
TabView(selection: $selectedTab) {
Text("Home")
.tabItem {
Image(systemName: "house")
Text("Home")
}
.tag(0)
Text("Settings")
.tabItem {
Image(systemName: "gearshape")
Text("Settings")
}
.tag(1)
}
}
}
enumを使って、各タブの持つ内容を一括で管理する
Tab
というenum
を作成します。
まず、今回は2つのTabを扱っているので、case
を次のように定義します。
+ enum Tab: String {
+ case home = "Home"
+ case settings = "Settings"
+ }
@ViewBuilder
を使用したコンピュ−テッドプロパティで、Viewの内容を定義する
さきほど、作ったenum
に@ViewBuilder
を使用したコンピュ−テッドプロパティtabContentを追加します。tabContent
は文字通り、Tab
のViewをクロージャで返すように実装しています。ここでは、switch
文を使って、enum
の各ケースに応じて異なるViewを生成しています。
enum Tab: String {
case home = "Home"
case settings = "Settings"
+ @ViewBuilder
+ var tabContent: some View {
+ switch self {
+ case .home:
+ Image(systemName: "House")
+ Text(self.rawValue)
+ case .settings:
+ Image(systemName: "gearshape")
+ Text(self.rawValue)
+ }
+ }
+ }
ちなみに、@ViewBuilder
は複数のビューを含むカスタムビューを作成する際に主に使用される属性です。プロジェクト作成時に作られるContentView
のbody
プロパティにも暗黙的に使用されています。
@ViewBuilder @MainActor
var body: Self.Body { get }
最後に、ContentViewをリファクタリングする
さきほど、作成したTab.swiftの内容をContentView
に反映させていきます。主な変更は次の2点です。
-
tabItem(_:)
メソッドでTab.(enumで定義したTab名).tabContent
という形への書き換え -
tag(_:)
メソッドでTab.(enumで定義したTab名)
という形へ書き換え
struct ContentView: View {
- @State private var selectedTab = 0
+ @State private var selectedTab: Tab = .home
var body: some View {
TabView(selection: $selectedTab) {
Text("Home")
- .tabItem {
- Image(systemName: "house")
- Text("Home")
- }
- .tag(0)
+ .tabItem { Tab.home.tabContent }
+ .tag(Tab.home)
Text("Settings")
- .tabItem {
- Image(systemName: "gearshape")
- Text("Settings")
- }
- .tag(1)
+ .tabItem { Tab.settings.tabContent }
+ .tag(Tab.settings)
}
}
}
このようにenum
を使うことで、Tabの定義を一元管理することができ、上記のように可読性を向上させることができました。また、Tabの数が増えた場合には、TabにCaseを追加することで簡単に拡張することができるようになりました。
おわりに
TabViewに直書きだったそれぞれのTabのコンテンツをenumを使って一箇所に記載することで可読性を向上させることができました。このリファクタリングによって、可読性の向上だけでなく、保守性、拡張性を向上させることができたと思います。
参考
Discussion