はじめに
CA Tech Loungeに所属している、iOS会員のよみです!
SwiftUIを書くようになって結構経ちました。UIKitから移行して、初めて覚えたテンプレートがこちら
var body: some View
ビューを定義するときに使用するフォーマットですよね。
いつも「バー ボディ サム ビュー」と言いながら打ち込んでいます。
そういえばsomeって何者?
var, body, Viewは分かる。だけどsomeってなんやねん。
今まで特に何も考えずに書いてたけどふとした時に気になったので、この機会に調べてみました。
ほぼanyと一緒
someは指定したprotocolに準拠しているものならどんな型でも受け入れられるやつです。
protocol Animal {
var name: String { get }
var age: number { get }
}
struct Dog: Animal {
var name: String { get }
var age: number { get }
}
struct Cat: Animal {
var name: String
var age: number
}
var pochi: some Animal = Dog(name: "ポチ", age: 3)
var tama: some Animal = Cat(name: "タマ", age: 2)
この例では、protocolで定義されているAnimalに準拠したDogとCatの構造体を定義します。
そして、someを使って型定義されたものに値を代入しています。DogもCatもAnimalに準拠しているので、エラーが出ることなく変数を定義できています。
ただanyと違うのは、一度代入されたら、その型から変更することができないという点です。
上の例を引き継ぐとこんな感じです。
var anyHachi: any Animal = Dog(name: "ハチ", age: 18)
var someHachi: any Animal = Dog(name: "ハチ", age: 17)
anyHachi = Cat(name: "ハチ", age: 12)
someHachi = Cat(name: "ハチ", age: 16) // エラー
はじめAnimalに準拠したDogを代入します。
これはsomeでもanyでもエラーは出ません。
でもそれぞれにAnimalに準拠したCatを再代入しようとすると、anyはエラーが発生しませんが、someはエラーが発生します。
「プログラミングはできるだけ制約を厳しくするのが基本」と習った私は、これからなるべくsomeを使うべきだと肝に命じました。
(と言ってもanyを使わなきゃいけない場面にすら今まで遭遇してないんだけど、技術力高い人たちはみんな使ってるのかな?)
なぜsomeを使うのか
それでは、ビューを定義する時になぜsome使うのでしょうか。
Viewにはいろんな部品がある
Viewに準拠したものはたくさんあります。Text, Button, VStack...
挙げればキリがありませんが、どれもViewの部品たちです。どの部品が定義されてもいいように、Viewに準拠したものをbodyに定義できるようにしてあるということですね。
別にあのフォーマットじゃなくてもいい
これまで、あのsomeがあったことで何かSwiftUIの特別な定義方法だと思っていたのですが、結構汎用的なものでできていたことがわかりました。
つまり、あれはただViewのprotocolに定義されたbodyに値を代入しているだけということです。
つまり、あのフォーマットじゃなくても一応Viewは定義することができます。
var body: some View = Text("Hello, Liquid Glass!").font(.largeTitle)
最初に書いたコードを、イコールを使って書き換えた形になります。初心者にも親近感の湧きやすいコードになったのではないでしょうか
このコードでも以下の画像のように表示できます。

さらに、この形であれば型定義も必須ではなくなるので、some Viewを削ることも可能です。
var body = Text("Hello, Liquid Glass!").font(.largeTitle)
こうなるともうただの代入にしか見えません。
最後に
この理解がなんの役に立つんだと言われればそれまでですが、今まで何も考えずに書いていたコードの解像度がグッと上がってとても楽しかったです。