プログラミング

SwiftUIの*Stack{ }やList{ }の謎を解く記事【波括弧は何?】

SwiftUIの*Stack{ }やList{ }の謎を解く記事【波括弧は何?】

はじめに

最近,ふと思い立ちSwiftの勉強を始めました.

そこでSwiftの多機能性に逆に悩まされています

今回の題材はSwiftUIでおなじみの VStack { } 系統.

この波括弧は何!?という私の疑問を解決する記事です.

もうすでに答えをわかっている人には「そんなこともわからんのかよ...」と呆れられそうですが,頑張ります.

問題のコード

以下のコードを見てください.

SwiftUIのチュートリアルをやれば似たようなコードを必ず見るはずです.

別にやっていることは分かります.

「水平方向にテキストとスペースを並べているんだな」というのは分かるんです.

そして, body がComputed propatyとして定義されていることも分かります.

でも,この HStack って何者なんでしょう??

関数ではなさそうです.

実際に定義を辿ってみました

どうやら構造体らしい.

でも構造体って初期化するならば, HStack( ) みたいな感じかと思っていたが, HStack { } という使い方をしている,なぜだ...

ヒントはクロージャ?

この HStack,イニシャライザの引数を見てみると,クロージャを含んでいる.

これがヒントなのかもしれないと思い,簡単な構造体をつくってみた.

自作のクロージャを引数にとる構造体

何の意味もないコードだが動作を確認するだけなので問題ない.

まずは初期化して実行

クロージャも超簡単なものを渡す.

問題ないし,特に疑問もない.

HStack { }のようにしてみる

おお!

これだ,同じような表記を実現することができた.

つまり, HStack { } の波括弧は引数に渡すクロージャを表しているらしい.

ここまでで,基本はわかった気がする.

しかし疑問がまだある.


クロージャ内に適当に積み上げられたオブジェクト

これ,一つの波括弧 { } 内にカンマ , もなく,オブジェクトが積み上げられてるけどどういうことなの?

見様見真似でやってみても...

もちろんダメ.

だってクロージャ内で複数文書くときは, return が必要なのだから.

またも定義を辿る.

すると,怪しげなものが.

@ViewBuilder

イニシャライザの @ViewBuilder content: () -> Content の部分.

この属性 (attribute) が関係しているに違いない,と調べてみると.

  1. SwiftUIの魔法を実現する仕組み (Custom Attributes, Function Builder) - Qiita

ピンポイントで求めてた記事を見つけました.

どうやら,この @ViewBuilder が付いたクロージャは以下のように解釈されるらしい.

が,こう👇

だから,実質クロージャ内は一つのオブジェクトしかないのでOKということ.

何だそりゃ.

便利なんだろうけど,細かく仕様を知ろうとする人にとっては,やや気持ち悪い

C++でいうところの,マクロ使いまくって構文が崩壊仕掛けている感じ.(?)

作ってみたい

だけど,仕組みがわかった以上,自分で同じような実装がしてみたい.

そして,先の記事では親切にも,その作り方まで書いてくれている.(神様!)

CustomAttribute

早速作ってみました.

意外と脳筋な実装になってしまうのですが,最大2つまで文字列を積み上げられるようにしました.

ちなみにメソッド名は buildBlock() と言う名前でなければダメっぽいです.

あとは引数のラベルは省略したいので, _ がついています.

早速実行してみる!

まずは,構造体のイニシャライザに作成したattributeを加筆します.

そしたら,待ちに待った実行!

やったー!嬉しいー!

これで,本題の謎は解けた気がします.

この,不思議構文はなかなか手強かったですね...

良い勉強になりました.

余談:@ViewBuilderの定義 (一部)

本家も脳筋な実装してました

最大9つスタックできるらしいです.

おわりに

いやー,謎が解けると気持ちが良いです.

私,こういう便利なフレームワークの定義を読み解くのが結構好きで,Pythonのフレームワークとかはよく読んでいたのですが,SwiftUIは手強かったですね.

勉強し初めて数日というのもあるし,結構細かい定義の話までしている記事って少ないんですよね.

みんな,「SwiftUIの使い方に特化している」というか.

あまり細かい定義のは話は気にならないのかな,理解できたらコーディングしやすくなると思うんだけどな.

みなさんはどう思います?

👉 Swiftでのアプリ開発を学ぶなら


スポンサードリンク