【SwiftUI】 今日のなんでやねん - @ViewBuilder


@ViewBuilder

よく見かけますが、なんのために使うのか。

 

■ 公式ドキュメント - ViewBuilder

A custom parameter attribute that constructs views from closures.

クロージャから View を構築するカスタムパラメータ属性。

You typically use ViewBuilder as a parameter attribute for child view-producing closure parameters, allowing those closures to provide multiple child views.

通常、ViewBuilderを子 View 生成クロージャパラメータのパラメータ属性として使用し、それらのクロージャが複数の子 View を提供できるようにします。


func contextMenu<MenuItems: View>(
  @ViewBuilder menuItems: () -> MenuItems
) -> some View

myView.contextMenu {
  Text("Cut")
  Text("Copy")
  Text("Paste")
  if isSymbol {
    Text("Jump to Definition")
  }
}

👉 ViewBuilder | Apple Developer Documentation hatena-bookmark

並列のまま、持ち運びできて、

記述が一層不要になるってことか。

 

■ if も使えるようになる


// NG
var body: some View {
    if imageName.isEmpty {
        return Text("no image")
    } else {
        return Text(imageName)
    }
}

@ViewBuilder
var body: some View {
    if imageName.isEmpty {
        Text("no image")
    } else {
        Image(imageName)
    }
}

var body: some View {
    Group {
        if imageName.isEmpty {
            Text("no image")
        } else {
            Image(imageName)
        }
    }
}

👉 SwiftUIのViewで条件によってViewを出し分ける方法 - The Pragmatic Ball boy hatena-bookmark

そういえば、

公式ドキュメントのサンプルコードにも、

しれっと if が入っていた。

なるほど、

Group / VStack / HStack がなければ使えなかった if を使えるようにしてくれるのか。

便利そう !

 

■ やってみた

こういうのがあったとして、


VStack {
  Text("top")
  Text("bottom")
}
.font(.title)
.foregroundColor(.red)

こう書ける。


TitleTextFormatView1 {
  Text("top")
  Text("bottom")
}

struct TitleTextFormatView1<Content: View>: View {
  @ViewBuilder var content: Content

  var body: some View {
    content
      .font(.title)
      .foregroundColor(.red)
  }
}

続いて、@ViewBuilder を消してみます。


TitleTextFormatView2 {
  Text("top")
  Text("bottom")
}

struct TitleTextFormatView2<Content: View>: View {

  // Type '() -> ()' cannot conform to 'View'

  var content: Content // *

  var body: some View {
    content
      .font(.title)
      .foregroundColor(.red)
  }
}

しかし、これは NG ですね、分かります。

勉強しましたから !

続きましては、

渡す View を VStack を使って、1つにまとめます。

他は変更ありません。

結果は、OK なはずです。


TitleTextFormatView3 {
  VStack { // *
    Text("top")
    Text("bottom")
  }
}

struct TitleTextFormatView3<Content: View>: View {
  var content: Content

  var body: some View {
    content
      .font(.title)
      .foregroundColor(.red)
  }
}

...

なんでや !?

 

■ まとめ

私はこれまで、

まず VStack や HStack を常に書いていたので

@ViewBuilder の必要性を感じなかった

ことが分かりました。

しかし、今回の結果は残念です。

謎です。

以下の基本的なキーワード、


「TupleView」
「Content」
「some View」
「any View」
「View | Stack | Layout」

分かりづらくないですか。

直感的にふんわりしてません ?

長い説明が必要ですよね ?

あなたの感想ですよね ?


【Android】「Navigation Bar」はどちらか分かりますか?

混乱しません?

【Android】「Navigation Bar」はどちらか分かりますか

【Android】「Navigation Bar」はどちらか分かりますか
👉 Window insets in Compose  |  Jetpack Compose  |  Android Developers hatena-bookmark

【Android】「Navigation Bar」はどちらか分かりますか
👉 Navigation bar – Material Design 3 hatena-bookmark

ネーミングややこしくない?

最近の Android 界隈。


ログインに使っている Twitter (X) アカウントの連携を削除する手順

Twitter (X) のアカウントで連携してログインしているサービスが不正アクセスされて情報が流出してしまうときがあります。


流出してからでは遅いのですが、確認しておくといいです。

 

連携を削除する方法

Twitter (X) アプリから進みます。


設定とプライバシー

 ↓

セキュリティとアカウントアクセス

 ↓

連携されてるアカウント

 ↓

(該当のアプリで)
アプリの許可を取り消す




再度、連携しているアプリを確認しておくといいと思います。

緊急でいつでも削除できるように。



将来、URL の twitter.com は x.com となるんだろうか。

アイコンが変わりました。

URLはどうなるのでしょうか。


❯ curl -I https://x.com
HTTP/2 302
date: Mon, 24 Jul 2023 14:24:27 GMT
location: https://twitter.com/
cache-control: private, max-age=0, no-store, no-cache, must-revalidate, post-check=0, pre-check=0
expires: Thu, 01 Jan 1970 00:00:01 GMT
server: cloudflare
cf-ray: 7ebcd3ab8e352615-NRT

❯ curl -I https://twitter.com
HTTP/2 403
date: Mon, 24 Jul 2023 14:24:21 GMT
perf: 7626143928
server: tsa_m
set-cookie: guest_id_marketing=v1%3A169020866196904294; Max-Age=63072000; Expires=Wed, 23 Jul 2025 14:24:21 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
set-cookie: guest_id_ads=v1%3A169020866196904294; Max-Age=63072000; Expires=Wed, 23 Jul 2025 14:24:21 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
set-cookie: personalization_id="v1_oj788V5nRvbYdR1OvohwoQ=="; Max-Age=63072000; Expires=Wed, 23 Jul 2025 14:24:21 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
set-cookie: guest_id=v1%3A169020866196904294; Max-Age=63072000; Expires=Wed, 23 Jul 2025 14:24:21 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None
x-powered-by: Express
cache-control: no-cache, no-store, max-age=0
x-transaction-id: dd0d24c26c46ed06
strict-transport-security: max-age=631138519
x-response-time: 182
x-connection-hash: 0a63336cc2c8ce1c490be21f121a4f8e8442c7a69dc1ee67c226dc672635b233

これは、どう考えるべきか。

完全移行しますかね。

しれっと、Unicode 文字も存在する。



スマホスタンド(充電不可)を作ってみたが、まあまあ使っている 📱

お香の香りって夏でも涼しげでいいですよね。



日本香堂 かゆらぎ 白檀 香立付 ホワイト 単品 40個 (x 1)

これの空き箱を木工用ボンドでくっつけちゃいます。

ただそれだけ。

台数が多くなると、立てておいた方が省スペースですし、視認性も良いですし。



日本香堂 かゆらぎ 白檀 香立付 ホワイト 単品 40個 (x 1)

ロック画面は常時時計表示にしておくのがおすすめです。

👉 Jake Wharton さん「Android12、ロック画面 / 常時表示の時計が良い。」  hatena-bookmark