公式チュートリアルで学ぶ SwiftUI 

<i>※本記事は、[一般に公開されている情報](https://developer.apple.com/tutorials/swiftui/handling-user-input)を元に作成しています。記事中の画像はApple Developerサイトのものを引用しております</i>

## これは何

WWDC 2019 で SwiftUI が発表されましたね！さっそく公式のチュートリアルも公開されているので、動かしながら SwiftUI を理解していきます。

## 実行環境

- macOS Mojave 10.14.5（18F132）
- Xcode 11 beta


## サンプルプロジェクトをビルドしてみる。

次のサンプルをダウンロードします。

[Handling User Input — SwiftUI Tutorials \| Apple Developer Documentation](https://developer.apple.com/tutorials/swiftui/handling-user-input)

`Complete`、 `StartingPoint` の2つのフォルダがありますが、今回は後者のフォルダにある xcodeproj をXcode 11で開きます。

そのまま実行すると次の画面が表示されるはずです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8292/34706dfc-b379-b211-7987-362808ed77f7.png)


## ソースコードを読んでみる

チュートリアルのソースコードを読んでいきましょう。

### リストに表示する行を作る部分

`LandmarkRow.swift` を開いてください。これがリストを構成するひとつひとつの「行」にあたります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8292/a586f86a-ae2a-0cbd-baca-87c503b19e42.png)

```swift
import SwiftUI

struct LandmarkRow: View {
    var landmark: Landmark

    var body: some View {
        HStack {
            landmark.image(forSize: 50)
            Text(landmark.name)
            Spacer()

            if landmark.isFavorite {
                Image(systemName: "star.fill")
                    .imageScale(.medium)
                    .foregroundColor(.yellow)
            }
        }
    }
}
```

LandmarkRow は `View` プロトコルを継承しています。このプロトコルには `body` というプロパティが定義されており、この中に表示するコンテンツを定義していきます。（つまり、body という名前を変更するとエラーになります）


[HStack](https://developer.apple.com/documentation/swiftui/hstack) は View を水平に並べていくためのものです。このブロック内で表示したい画像やtextなどを並べていきます。`Spacer()` でスペースを開けることも可能です。

また、この例では `Landmark` モデルの `isFavorite` プロパティによって表示/非表示を出し分けています。

### リストを表示する部分

次に `LandmarkList.swift` を開いてください。

```swift
struct LandmarkList: View {
    var body: some View {
        NavigationView {
            List(landmarkData) { landmark in
                LandmarkRow(landmark: landmark)
            }
            .navigationBarTitle(Text("Landmarks"), displayMode: .large)
        }
    }
}
```

同じように `body` に表示するコンテンツを定義していきます。

`NavigationView ` は名前の通りナビゲーション構造を実装するためのものです。

`List` の中では、<b>1行に表示するコンテンツ</b>を並べていきます。この例では先ほど作成した `LandmarkRow ` を1行あたり1つずつ表示しています。

ナビゲーションバーに表示するタイトルは `navigationBarTitle` でセットできます。

ちなみに、この LandmarkList を `SceneDelegate` でセットしているため、起動直後にこの画面が表示されるものと思われます。

### 画面遷移

`LandmarkList.swift` をちょっと修正して、行をタップしたら次の画面に遷移するようにしてみましょう。

```swift
import SwiftUI

struct LandmarkList: View {
    @State var showFavoritesOnly = false

    var body: some View {
        NavigationView {
            List(landmarkData) { landmark in
                NavigationButton(destination: LandmarkDetail(landmark: landmark)) {
                    LandmarkRow(landmark: landmark)
                }
            }
            .navigationBarTitle(Text("Landmarks"))
        )
    }
}
```

LandmarkRow を `NavigationButton(destination: LandmarkDetail(landmark: landmark)) {` で包んでいるのがポイントです。こうすることで、各行をタップすると `destination` に指定した view に画面遷移するようになります。また、その際に渡すデータもセットしています。

## 所感

SwiftUI は宣言的にUIが書けるのが楽しいですね。UITableView のように `cellForRowAtIndexPath ` や `didSelectRowAtIndexPath ` を定義する必要がないのはだいぶ楽です。個人的には Android の Groupie に使い方が似ているなーと感じました。

今回は単純にデータを画面に出すところまで解説しましたが、チュートリアルではトグルスイッチを使ったフィルタリングなども実装していますので、興味のある方は実際に動かしてみることをおすすめします！

## リンク

- [Handling User Input — SwiftUI Tutorials \| Apple Developer Documentation](https://developer.apple.com/tutorials/swiftui/handling-user-input) - チュートリアルはこちら
- [Xcode \- SwiftUI \- Apple Developer](https://developer.apple.com/xcode/swiftui/)