viewBuilderとは、
その名の通りViewをBuildする処理のことです。
swiftuiで構築していると、ここの部分は関数にして、Viewを返すような関数を作ってまとめたいなーって考えることもあるかと思います。
普通メソッドというと、returnで文字列型(String)や、Integer型(数値型)など定数を返すイメージですが、
よくよく考えると、
普段、普通に記載しているおまじないの
struct aaa:View{ var body: some view{ } }
はViewというプロトコルを継承していることによって、これはViewで表示するものと認識してくれています。
そして、上記簡単に書くと、
考えればbodyはstructのプロパティで属性です。
そしてこのようなプロパティの記載の方法は、クロージャと呼ばれる書き方で、
bodyという関数で返り値が複数のviewで返すような処理になっています。そのため、このbodyの中にはview型を記載しないといけません。
bodyはじゃあどういう関数によって構成されているのか?
それがViewBuilderというSwiftUIの機能につながります。
今まで関数でviewを返すことができないと僕は思っていたんですが、
普通のbodyで関数でviewを返しているんだなって思いました。
ViewBuilder
@ViewBuilderという宣言をして作成することで、
その関数はViewを返すことのできる特別な関数に生まれ変わります。
struct ContentView: View { var body: some View { Group(content: contentBuilder) } @ViewBuilder func contentBuilder() -> some View { Text("This is another way to create a Group 👥") Text("Just stack the views 🥞") } }
以下のようにすることで、2つのViewを返すようになっています。
ViewBuilderのコードを見ると、以下のように
buildBlock(_:)
buildBlock(_:_:)
buildBlock(_:_:_:)
...
buildBlock(_:_:_:_:_:_:_:_:_:_:)
と記載があります。
これは引数が1から10個まであり、
Viewは最大10個までしか作成できないことがここでなされているわけです。
Groupすることで、それが無しになり、
また別のViewを作成することができます。
Viewプロトコルを見る
Viewプロトコルに従うと、bodyは必ず指定しないといけません。
以下のようにViewプロトコルの定義にはそうなっています。さらにbodyは@ViewBuilderによって作成されているのもわかります。
ViewBuilderは、
@resultBuilderで検索すると以下のように出てきます。
こうなると、@resultBuilderと書かないとではないの?ってなるが、
独自でプロパティラッパーを作成する際、
@propertywrapper
struct aaa{
}
として作成し、
どこかで使う際は、
@aaa var moji:String
と使うのと同じで、
元々はresultBuilderという機能を使って生成しているみたいです。