ども、@kimihom です。
SwiftUI で開発してて、最も大きな謎であった print
の出力が動かない理由がようやく分かったのでまとめておく。
SwiftUI の基本記法
単にテキスト表示させる SwiftUI は
import SwiftUI struct ContentView: View { var body: some View { Text("Hello World") } }
となる。さて、ここで変数を持って print
で検証したいってケースは当然のように出てくるだろう。
import SwiftUI struct ContentView: View { var date = "2021/2/23" var body: some View { print(date) Text("Hello World \(date)") } }
これだけで、 body の {
の部分でエラーが発生する。
Type '()' cannot conform to 'View'; only struct/enum/class types can conform to protocols
何が原因なのか、全くわからない。しかもエラー記述場所は {
の部分から出てくる。この体験は SwiftUI プログラマーにとって大きな課題の一つになるであろう。
View 内は、そもそも Swift 文を書くところではない
SwiftUI の View 内では、 if文
も書けるし、ForEach
で繰り返し処理も書けるから、Swift 文を同じように書ける、と考えがちだろう。しかし、それは No である。
SwiftUI では ファンクションビルダと呼ばれる Swift 新構文によって、1行ずつ書いたコードが、自動で組み合わされる @_functionBuilder
という機能がある。
この ファンクションビルダを使うと、、衝撃のコードが実現できるようになる。
// @_functionBuilder で 文字を組み合わせる 自前 `StringBuilder の ab()` を定義 // `ab()` の実行 !!! @StringBuilder func ab() -> String { "こんにちは" "テスト" } print(ab()) // こんにちはテスト // 以下と同じ func ab() -> String { let a = "こんにちは" let b = "テスト" return StringBuilder.buildBlock(a, b) } print(ab()) // こんにちはテスト
今回の場合、String を組み足しただけのコードとなるが、なんと "こんにちは" "テスト" を文字列として各行に書くだけで、文字が足される処理を実装できる。ここは、Swift 構文ではなく、ファンクションビルダで定義した構文を書くことになるわけである。
そもそも SwiftUI ではなぜ for文
ではなく、ForEach
で書かなければならないのかもこれで理解できた。ForEach
は ファンクションビルダないで使える特殊な書き方であり、通常の for文
では ファンクションビルダとして書けないという理由なのだろう。
ただ if文
は普通の Swift コードを書いてるのと同じように書けてしまうので、最初は この var body: some View
内は普通の Swift 文をかけると誰もが思ってしまうことだろう。
終わりに
Swift を勉強してて もっと大きな謎だった "print 文が SwiftUI 内で書けない" 問題を理解することができた。 この問題の理由は、以下の本だけで知ることができた。
SwiftUI の本を4,5 冊くらい読んだけど, some
の定義は一旦なんなんだ? なんで print
が SwiftUI 内で書けないんだ? といった SwiftUI を最初に触る人が必ず思う疑問を、徹底して解説してくれている唯一の本だった。レベルが1上がった。

- 作者:金田 浩明
- 発売日: 2019/12/21
- メディア: Kindle版