【SwiftUI】リファレンスマニュアルの読み解き

SwiftUIはUIKitに比べて比較的簡単なコードで記述が可能です。

チュートリアルを進めるだけで、おおよそコードの書き方は理解できるのですが、いざリファレンスマニュアルを読んでいくと、予想外の構文が並んでいて戸惑ったので、改めて解読してみました。

スポンサーリンク

環境

この記事の情報は次のバージョンで動作確認しています。

【Xcode】11.1
【Swift】5.1
【macOS】Catalina バージョン 10.15
スポンサーリンク

テキスト(Text)

UIKitではUILabel部品に該当するViewです。

使い方は簡単で、

と、表示する文字列を引数で指定するだけです。

リファレンスマニュアルで、Text構造体のイニシャライザ(初期化子)を見ると次のようなっています。

まずはこれを読み解いてみます。

引数contentにはviewに表示する文字列を指定します。

"<S>"は引数contentの型であるSがジェネリクス(汎用)型である事を示します。

また"where S: StringProtocol"によって、型SがStringProtocol に準拠している事を表しています。

標準ライブラリでStringProtocolに準拠しているのはString型かSubString型です。

contentの引数ラベルが_(アンダースコア)で省略形である事を示しているので、引数名が不要となります。

結果的に引数にはString型の文字列"カピ通信"を渡すだけで想定通りの動作になるわけです。

スポンサーリンク

ボタン(Button)

UIKitではUIButtonに該当するView。

使い方はこんな感じ、

"タイトル出力ボタン"と表示されたボタンを押すと、文字列"カピ通信"がデバグエリアに出力される処理です。

この構文を、リファレンスマニュアルで見ると、次の通り。

まず1行目です、ここでは先程出てきた、ジェネリクスが使われています。

"<Label>"で型名Labelがジェネリクス(汎用)型である事、"where Label : View"でViewプロトコルに準拠している事を示します。

続いて2行目はButton構造体のイニシャライザ(初期化子)です。

1つ目の引数actionには、ボタンをタップした時に実行するアクションを定義します。

"() -> Viod"はクロージャー(無名関数)を示す表記です。

クロージャーには{}で囲んだ処理手続きの記述が可能であり、"-> Void"なので戻り値が無い事を示しています。

その前にある"@escaping"は、init()処理が終わった後も、クロージャーへの参照が残る事を表していますが、使う上で特に意識する必要はありません。

2つ目の引数labelも先のactionと同様で、クロージャーを定義します。

但し、"-> Label"とあるので、戻り値の型はLabelです。

型名Labelは1行目で示すように、Viewプロトコルに準拠する制約がありますので、Text()やImage()などのSwiftUI部品を記述する事ができます。

以上の説明から、Button部品は次のように使う事がわかります。

また、SwiftのクロージャーにはTrailing Closuresと呼ばれる書き方があります。

これは関数の引数の末尾(最後)がクロージャーの場合、処理部分を外に配置できる記述方法です。

先程のコードは次のように書き換えられます。

この方がすっきりして見やすいですね。

最後に"@ViewBuilder"について。

"@ViewBuilder"はカスタム属性定義で、後ろの引数labelの戻り値を複数設定する事が可能である事を示します。(最大10個まで)

ようするに次のような記述が可能です。

出力イメージはこちら

画像1:Button実行例

もう一つのイニシャライザ

Button部品にはもう一つ別のイニシャライザがあるので、そちらも読み解いてみます。

このイニシャライズには"Available when Label is Text."(ラベルがテキストの場合に使用可能)の但し書きがあります。

最初の引数titleがラベルに相当します。

titleの型名に相当するSは、その前の"<S>"でジェネリクス(汎用)型とわかります。

さらに後ろの"where S; StringProtocol"によって、String型あるいはSubString型に準拠する制約がつきます。

"action: @escaping () -> Void"は先程と同様で、ボタンをタップした時に実行するアクションをクロージャー(無名関数)で定義します。

関数末尾のクロージャーである為、処理部分を外に配置可能です。

総合すると次のような記述になります。

ラベルがテキストのみの単純なボタンであれば、こちらの記述の方がシンプルです。

スポンサーリンク

Viewのレイアウト(VStack)

VStackはViewを縦方向に並べる役割を持つ部品です。

リファレンスマニュアル上の構文は次の通り。

1行目では型名ContentがViewプロトコルに準拠している事を示しています。

@frozenは意味がよくわかりませんでしたが、たぶん気にしなくてもよさそうです。

2行目はVStack構造体のイニシャライザ(初期化子)です。

1つ目の引数alignmentには部品の配置方式をHorizontalAlignment型で指定します。

"= .center"はalignmentの初期値に.centerが設定されている事を表しています。

ちなみに、Structで引数の初期値が設定されている場合、引数の指定を省略する事が可能です。

続いて、2つ目の引数spacingには部品間の距離を指定します。

こちらも"= nil"がと初期値が設定されていますので、引数を省略する事が可能です。

最後の引数contentはViewプロトコルに準拠しているContent型を戻り値とするクロージャー(無名関数)、かつ関数の末尾ですので、処理部分を外に配置可能です。

"@ViewBuilder"はButtonの説明でも出てきたカスタム属性定義で、contentの戻り値を複数設定する事が可能である事を示すものでした。

これらを総合すると、次のような記述が可能になるわけです。

出力イメージはこちら

画像1:VStack実行例

スポンサーリンク

最後に

ほんのさわり程度ですが、SwiftUIのリファレンスを読み解いてみた記録です。

SwiftUI理解を進める足がかりになるかな?