RAKUS Developers Blog | ラクス エンジニアブログ

株式会社ラクスのITエンジニアによる技術ブログです。

SwiftUI チュートリアルの解説 【第1回:SwiftUIの基礎】

f:id:tech-rakus:20210716105303p:plain

はじめに

少し前の話になりますが、Appleから新しくSwiftUIという開発用のフレームワークが発表されました。
Appleの公式ページにSwiftUIのチュートリアルが全10章に分けられて公開されています。

https://developer.apple.com/tutorials/swiftui

f:id:crowd_k:20210713105840p:plain
※「Get Started」をクリックしてスタートできます。

最初は基本的な内容から始まり、後半には応用的な内容が出てきているので、SwiftUIを使ったアプリ開発の勉強にちょうど良いと感じました。
そこで、SwiftUIのチュートリアルの内容を解説してみようかと思います。
ただ、すべての内容を1つの記事にまとめると量が膨大になるので、今回は第1章の「Creating and Combining Views」を解説しようかと思います。

こちらには、SwiftUIの基本的な内容が記載されているので、本記事を読むことで簡単なアプリであれば作成ができるようになります。
チュートリアルは全て英語なので、初めてSwiftUIをやってみたいという人のハードルを下げられたらと思います。

SwiftUI とは

2019年ごろAppleが提供を開始した新しいiOSアプリ開発用のフレームワークで、以下のような特徴があります。

特徴

  • プログラムコード・データを更新した際に自動でViewのプレビューを更新

    • エミュレータ・実機で動作確認を行う必要がない
    • 開発効率が上がる
  • 実装方法がよりシンプル・直感的に

    • コードがシンプルになった
    • エンジニアの負担を軽減
    • 手を出しやすくなった

特に1番目に記載した、「自動でViewのプレビューを更新」は使っていてとても便利だと感じます。
※後ほど出てきます。

SwiftUIのチュートリアルを始める準備

まず前提として、Xcodeのバージョン11以降がインストールされているMacbookが必要になります。

また、SwiftUIチュートリアルページの赤枠で示したボタンをクリックして、Projectファイルをダウンロードしておいてください。
f:id:crowd_k:20210713110214p:plain

チュートリアルを進めるのに必要な画像ファイルなどが格納されています。
第一章を終えたときに完成するアプリの「完成版プロジェクト」も格納されているのでどうしても詰まったときは参考にすると良いと思います。

ここまでで準備は完了です。
早速、SwiftUIのチュートリアルを解説していこうと思います。

Section 1:SwiftUIのプロジェクトの作り方

以下の手順でSwiftUIのプロジェクトを作成してください。

  1. Xcodeを起動し、「Create a new Xcode project」を選択
  2. iOS > Single View app を選択
  3. 各種プロジェクトの設定を行う

    • User Interface」は、SwiftUIを選択してください。
    • チュートリアルではアプリ名を「Landmarks」と設定しているので特に決まっていなければ同じで良いと思います。
  4. 任意の場所にプロジェクトを保存する

※インストールからプロジェクトの作成の方法を詳しく解説している記事も書いているので、こちらも参考にしてみてください。
【超入門】Xcodeのインストール方法-iosアプリを実機にインストールするまで - RAKUS Developers Blog | ラクス エンジニアブログ

上記が完了すると、以下のような画面が表示されます。
f:id:crowd_k:20210713150119p:plain

プレビュー機能

プロジェクトを作成した直後ですが、すでに「Hello,World!」と表示されるコードが完成しています。
右上の方にある「Resume」を押下するだけでプレビュー機能を起動できるので、確認してみてください。
f:id:crowd_k:20210713145952p:plain

表示されている、「ContentView.swift」のコードを確認すると、次のようになっていると思います。

struct ContentView: View {
    var body: some View {
        Text("Hello,World!")
            .padding()
    }
}

3行目の「Hello,World!」の部分を任意の文字列に変更すると、右側のプレビュー画面に表示されている文字列もリアルタイムに更新されます。
f:id:crowd_k:20210713150331p:plain

前述した「自動でViewのプレビューを更新」は、この機能のことをさしています。
SwiftUIからデザインを確認しながらコードを書くことができるので、便利だと思います。

プレビューを表示させるための機能を担っているのが、コード中の以下の部分です。

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

previews内に指定されているViewのプレビューを表示します。
デフォルトでContentView()と記載されており、「Hello,World!」が表示されているということになります。
別のViewを作成し、previewsを編集することで、表示するViewを切り替えたり、複数のViewを同時に確認することができたりします。
SwiftUIでは、PreviewProviderを継承することで、このような機能を実装することができるようです。

Section 2:View要素を編集する

プロジェクトの生成直後、「Hello,World!」を表示させているコードは以下の部分になります。

        Text("Hello,World!")
            .padding()

Text()は、任意の文字列のテキストラベルを作成します。
コードを見るだけで何となくイメージすることができる非常に直感的なコードです。

後ろにくっついている.padding()は、そのView要素の周りに余白を作成します。
後ほどまた出てくるので、そちらで効果を確認してみてください。
(今はView要素が1つしかないのでわかりにくいです、、、)

同じ要領で、対象のView要素の後にコードをつなげることで、様々な編集を行うことができます。
例えば、チュートリアルに沿って以下のようにコードを編集してみます。

Text("Turtle Rock")
    .font(.title)
    .foregroundColer(.green)
            

f:id:crowd_k:20210713150653p:plain
プレビューを確認すると文字の色が緑色に変更され、文字サイズが大きくなったと思います。

Section 3:View要素を並べる

複数のパーツを並べるときは、HStackVStackZStackを使用します。
使い方は説明するより、コードを書いてプレビューを動かした方が分かりやすいと思います。

  • HStack:View要素を横(水平)方向に並べる
HStack {
        Text("Hello,World!")
            .font(.title)
        Text("Joshua Tree National Park")
                .font(.subheadline)
}

f:id:crowd_k:20210713151940p:plain

  • VStack:View要素を縦(垂直)方向に並べる
VStack {
        Text("Hello,World!")
            .font(.title)
        Text("Joshua Tree National Park")
                .font(.subheadline)
}

f:id:crowd_k:20210713151230p:plain

  • ZStack:View要素を画面に対して垂直方向に並べる  チュートリアルでは使用しないので、割愛します。

これらは、ネストさせることも可能です。
また、VStackは引数に、.leadingを渡すことで、各要素を左寄せにすることが可能です。
※他にも.centerで中央、.trailingで右寄せにもできます。

上記を屈指してチュートリアルのようにコードを編集します。

VStack(alignment: .leading)  {
    Text("Turtle Rock")
        .font(.title)
    HStack {
        Text("Joshua Tree National Park")
            .font(.subheadline)
            Spacer()
        Text("California")
            .font(.subheadline)
    }
}

HStackの内側が窮屈なので、Spacer()を挟んでいます。
名前の通り、スペースを作成します。

f:id:crowd_k:20210713152728p:plain

スタックのネストは、以下のようなイメージです。 f:id:crowd_k:20210714100500p:plain

Section 2 で出てきたpadding()を追加して、余白で見た目を整えて完成です。

VStack(alignment: .leading)  {
    Text("Turtle Rock")
        .font(.title)
    HStack {
        Text("Joshua Tree National Park")
            .font(.subheadline)
            Spacer()
        Text("California")
            .font(.subheadline)
    }.padding()
}

f:id:crowd_k:20210713153124p:plain
※両サイドに若干余白が生まれました。

SwiftUI では、基本的にこれまでのことを組み合わせてアプリの画面を設計していくことになります。
内容を理解すれば、以降は苦労することなく実施できるかと思います。

Section 4:SwiftUIのカスタム画像Viewを作成する

Viewの要素の中に、Image()というものがあり、名前の通り画像を扱います。
読み込んだ画像を表示させるだけでは味気ないので、このSectionでは 今風?なデザインに編集していく手順を説明しています。

まずは、あらかじめダウンロードしたプロジェクトファイルの中になるturtlerock@2x.jpgをプロジェクトに追加してください。
Assets.xcassetsに画像ファイルをドラッグ&ドロップして、追加できます。
f:id:crowd_k:20210713154457p:plain

画像を表示するためのViewを新しく作成するので、SwiftUIのファイルを追加してください。
上部の File > New > File... から、SwiftUI Viewを選択して追加することができます。
ファイル名はチュートリアルに習うのであれば、「CircleImage.swift」としてください。

最初と同じく、「Hello,World!」のテキストラベルを表示するコードが生成されます。
次のように編集すると、プレビューに先ほど追加した画像が表示されるはずです。

struct CircleImage: View {
    var body: some View {
        Image("turtlerock")
    }
}

f:id:crowd_k:20210713155301p:plain

"turtlerock"は、追加した画像ファイルの名前です。
このようにファイル名を引数でImage()に渡すことで 、該当の画像を表示させることができます。

後は Section 3 と同じ方法で、画像のViewを編集していきます。

struct CircleImage: View {
    var body: some View {
        Image("turtlerock")
            .clipShape(Circle())
            .overlay(Circle().stroke(Color.white, lineWidth: 4))
            .shadow(radius: 7)
    }
}

f:id:crowd_k:20210713155433p:plain

それぞれの説明です。
・.clipShape(Circle())
 .clipShape()は形を指定してViewを切り抜きます、
 今回は引数にCircle()を渡しているので、画像を丸く切り取る役割を担っています。
・.overlay(Circle().stroke(Color.gray, lineWidth: 4))
 .overlay()は、任意のViewを重ねて表示させることができます。
 Circle()は前述したとおり 丸 で、.stroke()は枠線を意味しています。
 以上からコードを見ると「円形の白い枠線」を重ねて表示しているということになります。
 ※lineWidthは枠線の幅を指定しています。
・.shadow()
 Viewに影を追加します。

以上です。
やはり、非常に直感的なコードです。

Section 5:他のフレームワークからのSwiftUI Viewを使用する

次は、MapKitを使って地図のViewを作成します。

Section 4と同様に新しくファイルを追加します。
チュートリアルに沿うなら、ファイル名は「MapView.swift」です。

importにMapKitを追加します。
ここがこれまでと違うところですね。

import MapKit

次にMapViewの中身を次のように変更します。

struct MapView: View {
    @State private var region = MKCoordinateRegion(
        center: CLLocationCoordinate2D(latitude: 34.011_286, longitude: -116.166_868),
        span: MKCoordinateSpan(latitudeDelta: 0.2, longitudeDelta: 0.2)
    )

    var body: some View {
        Map(coordinateRegion: $region)
    }
}

Map()をプレビューで表示するには、「ライブモード」に切り替える必要があるようです。
画像の赤丸で囲まれたボタンを押下することで、切り替えることができます。
f:id:crowd_k:20210713161008p:plain
チュートリアルの縮尺だと、表示範囲が狭いと感じたので 縮尺を広くとっています

順番に説明していきます。

  • region

これは、表示する地図の位置とその縮尺の情報を格納したプロパティです。
引数である、CLLocationCoordinate2D(latitude: 34.011_286, longitude: -116.166_868)で緯度と経度を設定し、該当するポイントが地図の真ん中に表示されるようになります。
2番目のMKCoordinateSpan(latitudeDelta: 0.2, longitudeDelta: 0.2)が縮尺を決める値です。
latitudeDeltaと、longitudeDeltaの値を大きくするほど、縮尺は大きくなります。

  • Map()

先ほど作成した、「表示させたい地図の情報」を引数で渡しています。
regionの情報を任意に変更することで表示させたい地図の場所、尺度を変更できるということです。

  • @State

これをつけたプロパティは、その値が監視されます。(使用するには、$をつける必要があります。 )
何らかの処理で変更が加えられたとき、必要に応じてViewが再描画されます。
今回で言うと、例えば何らかの処理でregion内の緯度と経度の情報が書きかえられたとき、それに応じて表示される地図も再描画されます。

Section 6:SwiftUIの詳細Viewを作成する

最後に、これまで作ってきたViewを組み合わせて、1つのViewを作成していきます。 Section 2、3 で作成した、ContentView.swiftの編集に移ります。

まず Stackを屈指して、上から「Section 5で作ったMapView()」、「section 4で作ったCircleImage()」の順で縦にView を並べ、説明文用のViewを追加します。
不格好なので、チュートリアルに従ってそれぞれのView要素を整理していきます。
以下がコードです。

struct ContentView: View {
    var body: some View {
        VStack {
            MapView()
                .ignoresSafeArea(edges: .top)
                .frame(height: 300)

            CircleImage()
                .offset(y: -130)
                .padding(.bottom, -130)

            VStack(alignment: .leading) {
                Text("Turtle Rock")
                    .font(.title)

                // 省略

                }

                Divider()

                Text("About Turtle Rock")
                    .font(.title2)
                Text("Descriptive text goes here.")
            }.padding()

            Spacer()
        }
    }
}   

f:id:crowd_k:20210713163741p:plain

  • .ignoresSafeArea():セーフティエリア外にもViewが表示されるようになります。
    iPhoneχ以降からある、画面上部のバッテリー残量などが表示されているエリアです。

  • .frame():表示されるViewの範囲を指定しています。

  • .offset():対処のView要素を移動させることができます。
  • .padding():余白を制御するやつですが、今回はマイナスの値で余白を小さくしています。
  • Divider():区切り線を引きます。(VStackの時は横線で、HStackの時は縦線がひかれるみたいです)

最後に、見出し部分のコードと見た目を整えて完成です。

HStack {
    Text("Joshua Tree National Park")
    Spacer()
    Text("California")
}
.font(.subheadline)
.foregroundColor(.secondary)

HStack内のText()についている.font(.subheadline)を外にくくりだすこともできるようです。
Stackに着けた場合は、その内部の全ての要素にコードが効くようです。

f:id:crowd_k:20210713165609p:plain

【おまけ】マウス操作だけでViewを編集する

チュートリアルにもかかれている、ちょっとしたTipsです。

1. 要素の編集を、コードを記述しないで行う
「control」+「option」を押しながらView要素のコードをクリックすると、マウス操作のみでViewの編集を行うことができます。

f:id:crowd_k:20210713175027p:plain
Font や Color などコードで設定したものも、マウス操作で変更可能です。
設定完了後、自動でコードが編集されます。

2. 要素の追加を、コードを記述しないで行う
マウス操作のみでView要素を追加することができます。

  1. 画面右上の「+」ボタンを押下する
  2. 追加したいView要素を選択
  3. コードまでドラッグ&ドロップする

f:id:crowd_k:20210713180616p:plain

さいごに

以上が第1章の解説になります。
解説した内容だけでも、SwiftUIをかなり使いこなせるようになると思います。
以降の章ではSwiftUIの画面遷移なども出てくるので、そちらも解説の記事を挙げられたらと思います。


  • エンジニア中途採用サイト
    ラクスでは、エンジニア・デザイナーの中途採用を積極的に行っております!
    ご興味ありましたら是非ご確認をお願いします。
    20210916153018
    https://career-recruit.rakus.co.jp/career_engineer/

  • カジュアル面談お申込みフォーム
    どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。
    以下フォームよりお申込みください。
    forms.gle

  • イベント情報
    会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください! rakus.connpass.com

Copyright © RAKUS Co., Ltd. All rights reserved.