Help us understand the problem. What is going on with this article?

SwiftUIの宣言的コーディングの読み方

この記事は何?

SwiftUI Tutorials を進めていくうちに、宣言的なコーディング が少しずつわかってきたので、忘備録として投稿します。

実行環境

macOS 10.15 Catalina beta7
Xcode11 beta7

修飾子の書き方

チュートリアルの序盤で、次の画面を構築する手順があります。

スクリーンショット 2019-09-04 21.28.39.png

この画面を構成している主なビューは、以下の通りです。

  • MapView(地図)
  • CircleImage(画像)
  • VStack(垂直に並べたテキスト)

実際のコードは、以下のように記述しています。

SwiftUIの宣言的コーディング
struct LandmarkDetail: View {
    var body: some View {
        VStack {
            MapView()
                .edgesIgnoringSafeArea(.top)
                .frame(height: 300)
            CircleImage()
                .offset(y: -130)
                .padding(.bottom, -130)
            VStack(alignment: .leading) {
                Text("Turtle Rock")
                    .font(.title)
                HStack {
                    Text("Joshua Tree National Park")
                        .font(.subheadline)
                    Spacer()
                    Text("California")
                        .font(.subheadline)
                }
            }
            .padding(.all)
            Spacer()
        }
    }
}

.xxx() は、修飾子と呼ばれまが、実際にはプロパティ値の指定と理解できます。
長ったらしく捉えると、この LandmarkDetail 構造体は以下のようなになります。

SwiftUIの宣言的コーディング
struct LandmarkDetail: View {
    var body: some View {
        VStack {
            MapView().edgesIgnoringSafeArea(.top)
            MapView().frame(height: 300)
            CircleImage().offset(y: -130)
            CircleImage().padding(.bottom, -130)
            VStack(alignment: .leading) {
                Text("Turtle Rock").font(.title)
                HStack {
                    Text("Joshua Tree National Park").font(.subheadline)
                    Spacer()
                    Text("California").font(.subheadline)
                }
            }
            .padding(.all)
            Spacer()
        }
    }
}

抽象的に捉えると、この LandmarkDetail 構造体は以下のようなコードです。

struct LandmarkDetail: View {
    var body: some View {
        VStack {
            MapView()
            CircleImage()
            VStack() {
                Text("Turtle Rock")
                HStack {
                    ...
                }
            }
        }
    }
}

body メンバープロパティがあるだけです。
この変数 body は、計算プロパティになっていますが、ひとつの VStack だけを返しているので、return キーワードは省略されています。

returnキーワードを明示
struct LandmarkDetail: View {
    var body: some View {
        return VStack {...}
    }
}

body プロパティ

body プロパティこそが、まさしくSwiftUIの本体だとわかります。

body
var body: some View {...}

View プロトコルに準拠した some型として宣言されています。
some 型は「とりあえず、なんでもいい」型という表現に見えます。
つまり、body は、アクセスされるたびに「何かしら View プロトコルに準拠した型」の値が割り当てられる変数なんですね。

Viewプロトコル

View プロトコルの宣言を見ると、body がありました。
他には見当たりません。
View プロトコルに準拠するには、body を実装すればいいんですね。

Viewプロトコルの宣言
public protocol View {
    /// The type of view representing the body of this view.
    ///
    /// When you create a custom view, Swift infers this type from your
    /// implementation of the required `body` property.
    associatedtype Body : View

    /// Declares the content and behavior of this view.
    var body: Self.Body { get }
}

コメントには
このビューの本体を表現するビューの型
カスタムビューを作成すると、必須プロパティ body の実装から型が推論される

...とあります。

考察

今のところ、SwiftUI宣言的コーディングの理解は...

  • View プロトコルに準拠させる
  • body はビューを1つだけ返す計算プロパティ
  • 修飾子は列挙できる
Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away