【iOS】初めてのSwiftUI 【Part1】

公開日: 2023/4/28 更新日: 2023/3/28

環境

・MacOS Ventura 13.0
・Xcode 14.2
・Swift version 5.7.2

1. プロジェクトの作成

プロジェクトを作成するとContView.swiftファイルが作成されるので開いてみます。


コードとレイアウトが並んで表示されます。

Hello worldと書かれている部分を変更してみると右側のレイアウトが即座に変更されているのがわかります。

ビルドしてレイアウトを確認する作業は繰り返すと意外と時間の掛かる作業なのでレイアウトの作成についてはかなり開発の効率は上がりそうです。

1-1. 文字列の表示

テキストの表示はText(“文字列”)で表示が可能です。UIKitでの同等の機能はUILabelです。

Text("Hello world!")

フォントの設定

.font()内で.を押すと候補が表示されます。

大きめのフォント.largeTitleを選択してみました。


テキスト色の設定

.foregroundColor()でテキストの色を変更可能です。文字列を黄色(.yellow)に変更してみます。


改行時のスペース設定

改行した際のスペースを設定します。.lineSpacing()にCGFloatで数値を入力します。

Hello, world!を2行表示してスペース50と500で違いを確認してみます。



行数の制限

テキストの行数の制限は.lineLimit()で設定します。nilを入力すると改行の制限なしとなります。


行数の制限を1行に指定してみました。

指定した行数にテキストが収まらない場合は…と表示されることがわかりました。

1-2. Label

SwiftUIのLabelは文字列とシステムアイコンや画像の名前を以下のように追加して表示します。

システムアイコンを追加する場所は以下のようにに追加します。

Label("文字列", systemImage: "システム画像")


スクリーンショットでは画像→文字列の順番で表示されていますが、表示する場所に応じて画像だけになったり、並び順が変わったりするそうです。

1-3. Image

画像の表示にはImageを使用します。

UIKitではUIImageViewにUIImageをセットしていたのが、SwiftUIではImage("画像名")で一瞬でできます。


画像のリサイズ

.resizable()で画像がスペースいっぱいに表示されます。

アスペクト比の設定

画面いっぱいにアスペクト比を保ったまま表示する場合は.resizableに加えて以下を追記します。

.aspectRatio(contentMode: .fit)

1-4. 図形の描画

図形の描画もシンプルなコードのみで追加できます。

四角形

四角形はRectangle()で描画します。

.fillで塗りつぶしカラーの指定、.frameで四角形のサイズを指定します。


円はCircle()で描画します。

塗りつぶし、サイズの指定は四角形と同じです。

1-5. ProgressView

大きいサイズのファイルの読込中などに使えるProgressViewは以下のように追加可能です。

ProgressView("読込中", value: 50, total: 100)

2. Layout

ここからはLayoutについて調べてみます。

2-1. Backgroundの使い方

.background()内で四角形を追加してProgressViewに背景色を設定してみました。


RadialGradientでBackgroundにグラデーションを設定してみました。

カラーの配列、センターの位置、半径の設定をします。


2-2. VStack

VStackは縦並びのレイアウト方法です。

VStack内にTextを連続して並べてみます。

VStackに対してフォントサイズを指定することで、3つのテキストに対してまとめてフォントの指定ができました。


区切り線の追加

区切り線の追加はDivider()と書くだけで簡単に設定できました。


2-3. HStack

HStackは横並びのレイアウトです。

Numberと区切り線のテキストが入ったレイアウトをそのままHStackのレイアウトに変更すると以下のような横並びのレイアウトになりました。


2-4. ZStack

ZStackは垂直方向のレイアウトになります。

コードで言うと一番最初に配置したものが一番奥に描画されてその上にUIパーツが積み重なっていくイメージだと思います。

スクリーンショットのレイアウトでは四角形の上にテキストが描画されています。


2-5. LazyVStack

LazyVStackは必要に応じてコンテンツを読み込む(表示されている部分のみ)ためパフォーマンスが向上すると説明がありました。

サンプルではScrollView内で使用されていたので大量に描画が必要になるときはこちらを使うべきなのだと思います。

サンプルコードではScrollView内にLazyVStackを設定、Textを100個描画しています。


var body: some View {
        ScrollView(.vertical) {
                   LazyVStack(spacing: 10) {
                        ForEach(0..<100) { index in
                            Text("\(index)")
                                    .frame(width: 200, height: 200)
                                    .border(.gray.opacity(0.5), width: 5)
                                    .background(.yellow)
                                    .cornerRadius(6)
                        }
                    }
                    .padding(.leading, 10)
                    .font(.largeTitle)
                }
    }


2-6. LazyHStack

LazyHStackもLazyVStackと表示に必要な部分の読み込みます。

先程のLazyVStackのコードScrollView()内を.horizontal、LazyVStack→LazyHStackに変更すると横スクロールで動作確認が可能です。

var body: some View {
        ScrollView(.horizontal) {
                   LazyHStack(spacing: 10) {
                        ForEach(0..<100) { index in
                            Text("\(index)")
                                    .frame(width: 200, height: 200)
                                    .border(.gray.opacity(0.5), width: 5)
                                    .background(.yellow)
                                    .cornerRadius(6)
                        }
                    }
                    .padding(.leading, 10)
                    .font(.largeTitle)
                }
    }

2-7. LazyVGrid

LazyVGridはScrollViewと組み合わせることでUICollectionViewに同様の機能が実装できます。

こちらも必要に応じてレイアウトに表示されるのでパフォーマンス外良いです。

サンプルでは4色の背景色を順番に設定し、3列で表示しています。

var body: some View {
        ScrollView {
            LazyVGrid(columns: columns, spacing: 10) {
                ForEach(0...100, id: \.self) { index in
                    Text("\(index)")
                        .frame(width: width / 3, height: width / 3)
                        .background(colors[index % colors.count])
                    .cornerRadius(8)
                }
            }
        }
        
    }

2-8. LazyHGrid

LazyHGridもLazyVGridと同様に実装できますが、ScrollView()に.horizontalの指定、LazyHGrid()内はcolumnsではなくrowsに変更する必要があります。

    let colors: [Color] = [.gray, .yellow, .red, .blue]
    
    var rows: [GridItem] =
    Array(repeating: .init(.flexible(), alignment: .center), count: 3)
    
    var body: some View {
        ScrollView(.horizontal) {
            LazyHGrid(rows: rows, spacing: 10) {
                ForEach(0...100, id: \.self) { index in
                    Text("\(index)")
                        .frame(width: 100, height: 100)
                        .background(colors[index % colors.count])
                    .cornerRadius(8)
                }
            }
        }
    }

3. まとめ

SwiftUIはコード量が少なく、レイアウトの変化を見ながらコードが書けるのが思っていたよりも快適でした。

UIKit,Storyboardから実装方法がかなり変わるので抵抗が有る方もいるかも知れませんが、触って見る価値が有ると思います。

まだまだできることが有ります。長くなってしまったので残りの部分はPart2で紹介していきたいと思います。