2006/01/19 (33)

id:yutailang0119 の通り、2026年1月19日に誕生日を迎えました。
ゾロ目。

Created by ChatGPT

昨年 yutailang0119.hatenablog.com

仕事

はてなブログアプリ

2025年はAndroid/Kotlinの仕事が多かった。*1
staff.hatenablog.com

はてなリスキリングプログラム」として、Androidアプリ開発経験のない若者と併走しながら、作りながらやっていきました。
prtimes.jp

自分自身も最新Kotlin状況やJetpack Compose経験ができて楽しかった。
こういった仕事を評価され、FY2025下半期の社長賞 (MVP) をいただきました。

最近はまたiOSの仕事が増えつつ、Androidも見ているという感じ。
モバイルアプリ以外も目にする機会が増えたが、自身の手を動かすところまで至れていない。

登壇

2025年は、Google Nest Camアプリとその拡張に手をやっていたので、発信もそれを題材にしたものが多め。

fortee.jp

Google Nest Camは買い足した。

猫との生活を豊かにするプログラミングが、とにかく楽しい。

生活

買ったもの

2025年早々にMacBookより高い買い物をしました。
詳しい話はオフラインで聞いて。

猫との生活

2匹目の猫を迎えました。
「レア」です、よろしくね。

yutailang0119.hatenablog.com

年始にCatlogシリーズ | Catlogを始めたので、何度もアプリで行動を確認しちゃう。

音楽

2025年は結構音楽コンサート行っていた。

中でもEXPO 2025 大阪・関西万博で行われた「ずっと真夜中でいいのに。 オモテEXPO」は貴重な体験でした。

33歳

今年の目標は「体力」。
普段から体力勝負で勝ってる暮らし方、働き方なのですが、きっかけがありまして。
2026年年明けから、数日体調不良で倒れていました。
体調不良で寝込んだのは、十数年ぶりな気がします。

11月中旬から1月上旬あたりには先住猫のビビも風邪だったり、便秘だったりで不調そうで、病院に行ったりが発生しました。
自分が倒れている間に悪化ということがなくてよかったのですが、何かあった時に人間が倒れてる場合ではない。
高齢の分類になる猫年齢なので、いつでもケアできる体制にします。

最後に

猫がよろこびます。

www.amazon.jp

*1:このブログもAndroidアプリで書いています。

SwiftUI.NavigationSplitViewとList.selectionのBinding

はてなエンジニアアドベントカレンダー2025 50日目の記事です。

SwiftUIのNavigationSplitViewを使ってるアプリは多くありません。
また、詳細な解説記事も少なく、最初は自分も誤用していました。
【SwiftUI】NavigationSplitView誤用しててonAppear呼ばれなかった件

今回は、NavigationSplitViewListを組み合わせた場合の挙動を見ていきます。

お題

まずは今回のお題を整理します。

環境

  • Xcode Version 26.2 (17C48)
  • SWIFT_VERSION = 6.0
  • iOS/iPadOS 26.2

今回は簡略化のためNavigationSplitView.init(sidebar:detail:)を採用します。
sidebarにList表示、detailにList選択の詳細表示といった具合です。
NavigationSplitView.init(sidebar:content:detail:)は3カラムになりますが、利用方法は同じです。

Listは標準的すぎて扱いづらいという意見もありますが、プラットフォームごとのLook and Feelが適用されるので、好んで使用しています。

表示データ

表示用のデータは以下を用います。
Listに表示、selectionにBindする都合、HashableかつIdentifiableにしています。

struct Symbol: Hashable, Identifiable {
  var name: String
  var emoji: String

  var id: String { name }

  static var symbols: [Symbol] {
    [
      Symbol(name: "Rat", emoji: "🐀"),
      Symbol(name: "Ox", emoji: "🐂"),
      Symbol(name: "Tiger", emoji: "🐅"),
      Symbol(name: "Rabbit", emoji: "🐇"),
      Symbol(name: "Dragon", emoji: "🐉"),
      Symbol(name: "Snake", emoji: "🐍"),
      Symbol(name: "Horse", emoji: "🐎"),
      Symbol(name: "Goat", emoji: "🐐"),
      Symbol(name: "Monkey", emoji: "🐒"),
      Symbol(name: "Rooster", emoji: "🐓"),
      Symbol(name: "Dog", emoji: "🐕"),
      Symbol(name: "Boar", emoji: "🐗"),
    ]
  }
}

List表示とDetail遷移

表示と遷移を実装します。

実装

struct SplitView: View {
    @State private var selection: Symbol?

    var body: some View {
        NavigationSplitView {
            Sidebar(selection: $selection)
        } detail: {
            Detail(selection: selection)
        }
    }
}
[f:id:yutailang0119:20260117135652p:plain][f:id:yutailang0119:20260117141443p:plain]
extension SplitView {
  struct Sidebar: View {
    private let symbols: [Symbol] = Symbol.symbols
    @Binding var selection: Symbol?
    
    var body: some View {
      List(symbols, id: \.self, selection: $selection) {
        Text($0.name)
      }
    }
  }
  
  struct Detail: View {
    let selection: Symbol?
    
    var body: some View {
      if let selection {
        Text(selection.emoji).font(.largeTitle)
      } else {
        ContentUnavailableView("Select from sidebar", systemImage: "pawprint")
      }
    }
  }
}

実行

Regularサイズ表示 選択状態

GIF

Regularサイズ表示、選択状態

Detailへの表示とList.selectionをBindすると、選択状態がListに反映されます。
iPhone表示だと見えづらい部分ですが、表示条件分けを意識する必要がないのは素晴らしいですね。

Overviewにもある通りですが、List.selectionに適切にBindすると、List (またはその内部のForEach)に表示するRowContentはNavigationLinkにする必要はありません。
それどころかButtonでなくとも、Listがタップを判定してselectionに状態を伝えてくれます。

一点不明なのは、ドキュメントのサンプルにはない id: \.self, を指定しないと、Bindが動かなかったことです。
Identifiableなのですが...

List以外からの遷移

SidebarのToolbarからDetailに別画面を表示したいことは、典型的なユースケースです。
Detailの選択肢をenumで表現しましょう。

enum Selection: Equatable {
  case symbol(Symbol)
  case cats
}

実装

型が異なり、直接@BindingにBindできない箇所には、Binding.init(get:set:)を使って変換します。

struct SplitView: View {
  @State private var selection: Selection?

  var body: some View {
    NavigationSplitView {
      Sidebar(
        selection: Binding {
          switch selection {
          case .symbol(let symbol): symbol
          case .cats, nil: nil
          }
        } set: {
          selection = $0.flatMap(Selection.symbol)
        }
      )
      .toolbar {
        ToolbarItem(placement: .topBarLeading) {
          Button {
            selection = .cats
          } label: {
            Label("Cats", systemImage: "cat")
          }
        }
      }
    } detail: {
      Detail(selection: selection)
    }
  }
}

extension SplitView {
  struct Sidebar: View {
    private let symbols: [Symbol] = Symbol.symbols
    @Binding var selection: Symbol?

    var body: some View {
      List(symbols, id: \.self, selection: $selection) {
        Text($0.name)
      }
    }
  }

  struct Detail: View {
    let selection: Selection?

    var body: some View {
      switch selection {
      case .symbol(let symbol):
        Text(symbol.emoji).font(.largeTitle)
      case .cats:
        Text("🐈🐈<200d>⬛").font(.largeTitle)
      default:
        ContentUnavailableView("Select from sidebar", systemImage: "pawprint")
      }
    }
  }
}

実行

Regularサイズ表示 選択状態

しかし、Compact表示 (iPhone) ではToolbarのボタンからの遷移が機能しません。

Catボタンから遷移しない
デバッグしてみるとDetail: ViewonAppear(perform:)は呼ばれ、 onDisappear(perform:)は呼ばれていませんでした。
NavigationSplitViewの表示管理がうまくいっていないようです。

この場合はNavigationSplitViewColumnのState管理を、自分でやるとうまくいきます。

Binding<NavigationSplitViewColumn>

NavigationSplitView.init(preferredCompactColumn:sidebar:detail:)を使うと、外側からNavigationSplitViewColumnをBindできます。
preferredCompactColumn: Binding<NavigationSplitViewColumn> なので、変化に連動してNavigationSplitViewが表示するカラムを決定します。

実装

struct SplitView: View {
  @State private var preferredColumn: NavigationSplitViewColumn = .sidebar

  var body: some View {
    NavigationSplitView(preferredCompactColumn: $preferredColumn) {
      Sidebar(...)
    } detail: {
      Detail(...)
    }
    .onChange(of: selection) { _, newValue in
        preferredColumn = newValue == nil ? .sidebar : .detail
    }
  }
}

onChange(of:initial:_:)で、preferredColumnを更新するのがポイントです。
これで selection = .cats の代入に合わせて、preferredColumn = .detail が行われ、画面遷移が動きます。

実行

Catsに遷移できるようになった

まとめ

SwiftUI.NavigationSplitViewとListを組み合わせた画面遷移、選択状態の管理を解説しました。
NavigationSplitViewはクセが強いやつで、この他にも知らないと引っかかる罠が存在しますが、扱えるようになると選択できるUI表現の幅が広がります。
2026年はNavigationSplitViewが使われるアプリが増え、知見が広く共有されることを期待しています!

はてなエンジニアアドベントカレンダー2025

今年もお疲れ様でした。 はてなエンジニア Advent Calendar 2025 - Hatena Developer Blog
よいお年を!🐍🔜🐎

🐈🐈‍⬛

今年飼って良かった猫2025

onishi.hatenablog.com

これまで表彰を行なっていませんでしたが、今年から我が家でも開催します。

最優秀賞

今年の最優秀賞はもちろん「ビビ」さんです。
おめでとうございます🎊

審査員コメント

昨年に引き続き、愛くるしさ満点でした。


id:yutailang0119 の技術を陰から支えた功労者。 yutailang0119.hatenablog.com


今年から設置したこたつを早くも占領。

同率最優秀賞

なんと、今年は最優秀賞がもう一匹。
新入りの「レア」さんです。
おめでとうございます🎉

レアプロフィール

  • 🆕 2025/10~
  • 黒猫
    • エンジェルマーク
  • メス
  • 6ヶ月 (推定)
    • 元野良猫 (保護猫)
  • 保護時の名前はカトレア (Cattleya) -> レア

9月末に譲渡会参加、10月頭にトライアル開始で、そのまま正式譲渡となりました。
我が家に来て3ヶ月弱、すっかり我が物顔で闊歩しています。

前評判通りに、黒猫はどこにいるかがわからなくなります。
そして写真が映えない、顔どこ。

控えめな性格と聞いていましたが、トライアル中からアグレッシブに駆け回っていました。
猫が大好きなようで、先住のビビにまとわりついては、うざがられています。
仲良く、健やかに過ごしておくれ。

2匹の様子 🐈🐈‍⬛

まとめ

2匹になって、ドタバタがかなり増え、仲良くやってくれています。
ビビは運動量が増えたのか、ダイエットに成功しました。
レアはまだ子猫なので高いところに登ったり、おもちゃで遊んだりと大変ですが、お迎えしてよかった。

来年もよろしくお願いします。

ご支援はこちら www.amazon.jp

iOSDC Japan 2025に参加 & LT登壇しました 🐈 #iosdc #iwillblog

今年もiOSDC Japan 2025に参加してきました。 iosdc.jp

発表

fortee.jp

VNDetectAnimalBodyPoseRequest

採択

今回はiOSDCをターゲットにしたネタ準備ではなく、日常の内容で勝負しました。
この1 - 2年間のプライベートな開発は、猫との生活をよくするにはをやっているのでした。
こんなに猫を溺愛していることに、自分でもビックリします。

他プロポーザルで方向が近いものが上がってきて、そちらもおもしろそうだけど、このネタでは自分がやりたいと強く思っていたので、採択通知に安堵しました。
内容自体はかなり濃いものなので20分でも語り尽くせない感じなのですが、だからこそLTでバチっとやるとウケるだろうなとも思っていたので、思惑に合致できてよかった。

準備

技術面を5分にすべて詰め込むことは難しく、「できること、やっていること」に絞り、実装は見せる程度に留めています。
一方で猫のアピールばかりでも反応は二極化するだろうと思うので、ちょうどよい配置に悩みました。

題材として、やはりライブ感の演出が重要だろうと思ったので、録画 < 実演を目指して準備しました。
初めてmtj0928/SlideKitを使って、なんとか満足できる仕上がりになった。

実演するとなると、現地にGoogle Nest Camを持って行くか、自宅を映すかになります。
Google Nest Cam側のコネクション安定に少しだけ不安があったので、自宅を映すことしました。*1
自宅を映すとなると、次の懸念は現地にいる自分は直前に手直しができないので、家を出る前の準備を入念にすることになります。
カメラの画角を決めたり、見える位置に時計を移動させたり。

録画についても、できる限りいい映像をお届けしたので、何度も撮り直しました。
とは言っても猫は気まぐれなので、カメラ画角に入ってきたら人間が静かに準備して、撮影を始めるということを何度も繰り返した。
時には、ライトで誘導したり、おもちゃで興味を引いたり。

発表の大枠ができてタイムを測ると概ね5分。
デモのネットワーク通信に振れがあるので、トークでは飛ばしてもいい箇所をいくつか設定して、想定の進行に戻れるポイントを用意していました。
逆に録画部分は一定の時間で進むので、進行については安心しつつ、スクリプトに合わせた動画時間に何度か編集しました。

いよいよ発表

前述のネットワークをずっと気にしていたので、事前に会場ネットワークチームに相談して、可能であれば今の設定は変えないでくれとお願いしたり、不安があれば有線も用意できるよとアドバイスいただいたりしました。
1度目のデモがなかなか繋がらずに「やったか...」思ったんですが、無事にスクリーンに映り、会場からも反応が返ってきてよかった。

LTの5分間って、話す、時間管理はもちろん、会場の反応を見る、カメラに目線を上げる、...とやることが多いのですよね。
今回の会場はこれまでの横長ではなく、縦長だったので人の多さを余計に感じました。

ニコ生タイムシフトで自分を見てみましたが、手前味噌ながらも反応よかったのではないか。
コメントで「(Smart Device Management APIの)初回5ドルは一回だけ?」との質問をいただいていたのでここで回答すると、Smart Device Management APIの登録料 = Device Access Consoleの登録料と読み替えてもらいたく、Googleアカウントにプロジェクトを作る権限を付与するための初期費用だと思ってもらえるとよいです。
個人で使う分には十分だと思いますが、一般にリリースした時のユーザー数やリクエスト数上限解放には別に重量課金が必要になると考えてください。
ここの仕組みはGoogle Cloudに乗っています。

今回の発表は自分史上もっとも手応えのあるトークにできました。
発表後、猫を飼っている方とお話しできたし、ちょうど猫を飼い始めてカメラを検討していたという話も聞けて、会話できたのがよかったです。
ビビがかわいかったという感想も、たくさんいただきました。
Xでの投稿もありがとうございます!!!

ビビへのファンレターはすべて本人に伝えますので、ぜひフィードバックからお送りください。
https://fortee.jp/iosdc-japan-2025/me/feedback/292e2ec3-d74b-49a6-a8cb-63c2883d589e

発表の中での反省は2つ。
マイク音のチラつきを気にしながら話すようにしていましたが、揺れのノイズが少なからず入っていたようです。
握りを強くしようと思ったら、マイクの網に触れてしまっているのもマイナス。

発表での配信カメラの位置を確認し忘れたのも反省点。
画角から半身がズレがちだったので、その点に気をつけたい。

タイトルコールの名前読みにも反応をもらいました。

fortee.jpのスピーカー設定の読み方欄を見て、ピンと来ました。
2025年が立木さんのタイトルコールかはわかりませんでしたが、絶対「ビビ」と呼んでもらいたいと思いつきました。

お名前の読み方(カタカナ)

当然 pronounce 用で、運営から指摘されたら直すつもりで出しているので、あまり遊びすぎると制限されるかもです、自己責任で。 *2
ただ、タイムテーブルに表示される名前に乗っていると先バレしてしまうので、読み方だけ編集しました。
結果怒られなく、無事に1人と1匹揃って名前を呼んでもらって感無量です。

スピーカープロフィールよりも、タイトルに🐈が入っていて困ったとは聞きました。
パンフレットや配信画面の表示は、絵文字での苦労を感じますね。

他にも仕込みをいくつかしていて、スライドに猫が映るから、その写真も撮影しておいてねとお願いしておいたり、

lestrrat.ldblog.jp

発表内容はこうなので、発表に合わせた関連リンクを出してもらえると助かります、と依頼しておいたり。

トーク

現地でのトークを聞く時は、基本Aを選んでおくかなというつもりで、アンカンファレンスに顔を出したりしながら過ごしました。
A以外ではukitakaさんの あなたの知らない「動画広告」の世界 〜実装して理解する動画広告のしくみ〜 by ukitaka | トーク | iOSDC Japan 2025 #iosdc - fortee.jp が気になって聞きに行った。
(作りませんが、) こんな手法でブロッカーが作れるんじゃないかと想像できて、ではどう対策するかも考えながら聞いていました。

Swift Buildやコンパイラをさらに身近に生活したいな〜とも思った。
Swiftビルド弾丸ツアー - Swift Buildが作る新しいエコシステム by giginet | トーク | iOSDC Japan 2025 #iosdc - fortee.jp

祝開催10回

初回の2016から参加している、すべてを知る者です。
せっかくの機会なので、読み直して感想を書いてみます。

2016

iOSDC Japan 2016楽しかった!!! <2016/08/20> - がんばってなんか書く

若すぎる、自分の過去だけど、キラキラして見えました。
iOSDCの開催と共に、自分も成長してきたことを感じます。

あと毬花という名前のビールおいしかったです。

iOSDC Japan 2016楽しかった!!! <2016/08/20> - がんばってなんか書く

9年後の君は、うまいビールに詳しくなっているよ。

2017

ブログを書くまでがiOSDC JAPAN 2017です! #iosdc - がんばってなんか書く

LT内でも話したのですが、 200字程度 と設定されている概要部分に700字を超えるCfPを出して、これ以降フォームにバリデーションをかけられました。

ブログを書くまでがiOSDC JAPAN 2017です! #iosdc - がんばってなんか書く

今もやってることが変わってないな...
2016に来年はプロポーザルを出すと書いていて、ちゃんと通せていてえらいね。

2018

iOSDC Japan 2018に参加 & LT登壇しました #iosdc - がんばってなんか書く

現職に転職していますね、京都からやってくるようになっていた。
写真に写っている半分くらいはメンバー変わっていない気がする。
3.5日やっていたらしい、正気?

2020

iOSDC Japan 2020に参加 & LT登壇しました #iosdc - がんばってなんか書く

オンライン開催での感想、また集まれるようになってよかった。
xcrunについて話していて、こういうのに凝っていた頃だった。

おもしろい

2022

iOSDC Japan 2022にオフライン参加した #iosdc - がんばってなんか書く

オフライン開催に大変喜んでいそう。
楽しすぎてずっと飲み歩いていたと思う。

最終日に帰るプランで組んでいて、新幹線終電まで走ったことを覚えています。

2024

iOSDC Japan 2024に、パンフレット投稿で参加しました #iosdc - がんばってなんか書く

初めてパンフレット投稿をやった年です。
開催前の忙しさはあるけど、当日はプレッシャーなく、スピーカー扱いなのでいいなと思ったはず。
ただ、やったことがあるものだけが共感できる苦労を感じれました。
商業雑誌には何度か出したことはあったけど、別のあれこれがあったので、簡単ではない!

今回は、隠さず素直に認知できてないことを誤って、X交換させてもらえますかと言えた。
交流は少しずつでも増やし続けられていてよかったよかった。

毎年は書けてない、すみませんでした。
自分がプロポーザル提出、採択された年はちゃんと参加記を残しているみたい。
記憶では話していない年は、プロポーザルを出せていない年だったと思うので、採択通せているっぽい。

来年は10周年

10回目の次は、10周年ということで来年もきっとお祭りでしょう。
トークに限らず、来年も魅力ある交流ができるように精進して参ります。

スタッフの皆さん、ありがとうございました。
自分もおつかれ様

*1:iOSDCのネットワークは信頼しているし、相談もできると思います。

*2:特に声優さんには、読み上げてもらえない表現もありますからね

iOSアプリでGoogle Nest CamにWebRTC接続

yutailang0119.hatenablog.com

の続編

WebRTC

webrtc.org

Web Real-Time Communicationの略で、動画や音声、データの相互通信する規格のことです。

It supports video, voice, and generic data to be sent between peers

WebRTC API - Web APIs | MDNが詳しく解説されています。

iOSでのWebRTCライブラリ

iOSアプリでGoogle Smart Device Management APIを使う (2025) - がんばってなんか書くでは

WebRTCのライブラリがないので、情報お待ちしております!

と終わったので、その後の調査から。

残念なことに、Googleからのモバイル向けの公式バイナリは配布停止されています。
PSA: WebRTC M80 Release Notes

WebRTC自体はオープンソースプロジェクトとして公開されているので、https://webrtc.googlesource.com/src を自分でコンパイルすれば使用可能です。
が、Swift Package Managerで手軽に管理したいので、今回は stasel/WebRTC を利用することにします。
Binary Targetとして、ビルド済みxcframeworkをリンクしてくれるので便利。

Smart Device Management APIを介したWebRTC接続

WebRTCの魅力の一つは相互に送受信できることですが、Nest Cam側の映像、音声を受信することに絞って考えます。
Nest Camにはスピーカーが付いているので、音声を送信することもできそうな気がする。
NSMicrophoneUsageDescriptionが必要になるはず。

手順

  1. RTCPeerConnectionを作成 w/RTCDataChannel
  2. SDP Offerを生成
  3. SDM APIにSDP Offerを送信
    • sdm.devices.commands.CameraLiveStream.GenerateWebRtcStream
  4. SDP Answerを受信
  5. RTCPeerConnectionにAnswer SDPを適用
  6. 受信開始

WebRTC接続確立手順
Online FlowChart & Diagrams Editor - Mermaid Live Editor

1. RTCPeerConnectionを作成 w/RTCDataChannel

Factoryが用意されているので、必要な設定を詰めてRTCPeerConnectionを作成。
RTCDataChannelも接続します。

import WebRTC

let factory = RTCPeerConnectionFactory()
let constraints = RTCMediaConstraints(
  mandatoryConstraints: [
    kRTCMediaConstraintsOfferToReceiveAudio: kRTCMediaConstraintsValueTrue,
    kRTCMediaConstraintsOfferToReceiveVideo: kRTCMediaConstraintsValueTrue,
  ],
  optionalConstraints: nil
)
guard let peerConnection = factory.peerConnection(
  with: RTCConfiguration(),
  constraints: constraints,
  delegate: nil
) else {
  return
}
let dataChannelConfiguration = RTCDataChannelConfiguration()
dataChannelConfiguration.isOrdered = true
_ = peerConnection.dataChannel(forLabel: "foobar", configuration: dataChannelConfiguration)

2. SDP Offerを生成

RTCPeerConnectionから、OfferのSDPを生成。
RTCPeerConnection にLocal descriptionとして、適用します。

do {
  let offer = try await peerConnection.offer(for: constraints)
  try await peerConnection.setLocalDescription(offer)
} catch { ... }

3. SDM APIにSDP Offerを送信

Smart Device Management APIのCommandを使って、WebRTCを生成します。

sdm.devices.commands.CameraLiveStream.GenerateWebRtcStream

POST /enterprises/project-id/devices/device-id:executeCommand
{
  "command" : "sdm.devices.commands.CameraLiveStream.GenerateWebRtcStream",
  "params" : {
    "offerSdp" : "\(offer.sdp)"
  }
}

4. SDP Answerを受信

APIレスポンスの answerSdp を使います。

{
  "results" : {
    "answerSdp" : "answerSdp",
    "expiresAt" : "2020-01-04T18:30:00.000Z",
    "mediaSessionId" : "Bshco5XLhPxzdJYfQn7Kwtp4yd..."
  }
}

5. RTCPeerConnectionにAnswer SDPを適用

RTCPeerConnection にRemote descriptionとして、適用します。

do {
  ...
  try await peerConnection.setRemoteDescription(
    RTCSessionDescription(type: .answer, sdp: response.results.answerSdp)
  )
} catch { ... }

6. 受信開始

RTCPeerConnectionからRTCVideoTrackを取り出し、

let videoTrack = peerConnection.transceivers
  .first(where: { $0.mediaType == .video })?
  .receiver.track as? RTCVideoTrack

RTCMTLVideoView に表示

import SwiftUI

struct VideoView: UIViewRepresentable {
  var videoTrack: RTCVideoTrack

  func makeUIView(context: Context) -> RTCMTLVideoView {
    let view = RTCMTLVideoView()
    view.videoContentMode = .scaleAspectFit
    return view
  }

  func updateUIView(_ uiView: RTCMTLVideoView, context: Context) {
    videoTrack.add(uiView)
  }
}

表示

youtu.be

Desing for iPadとして、macOSやvisionOSでも実行可能です。

おわり

宣伝

さらにこの先の拡張について、iOSDC Japan 2025にプロポーザルを応募しています。
お気に入り、応援よろしくお願いします!!!

2025/01/19 (32)

id:yutailang0119 の通り、2025年1月19日に誕生日を迎えました。
片手で数えられなくなった。

昨年 yutailang0119.hatenablog.com

仕事

ジャンプ+が出たよ!
はてなのアプリ専用マンガビューワを集英社が採用。2,700万ダウンロードを超える「少年ジャンプ+」に提供開始 - プレスリリース - 株式会社はてな

はてなのポッドキャスト Backyard Hatena #38 - GigaViewer for Apps と開発合宿と(id:yutailang0119) #byhatena - Hatena Developer Blog で、いろいろと話しています。

社内ではグレード改定があって、数字上はS4からS5になりました。
入社からこれまでの話もまとめたので、こちらも参照ください。 yutailang0119.hatenablog.com

生活

Apple Vision Pro

ハワイまで弾丸ツアーで買いに行きました。
まだまだ行動力あるなと思う。

yutailang0119.hatenablog.com はてなエンジニアによるApple Vision Pro座談会 - Hatena Developer Blog

社外でもYoutube活動を始めました。
チャンネル登録、高評価お願いします!

www.youtube.com

音楽フェス

初めての音楽フェスでMETROCK 2024に行く機会があり、生の音楽を聴くのはいいなとなりました。
年末にはRadio Crazy 2024にも参戦した。

フェス以外にライブも行く機会が多くて、fripSidePeople in The Box 、Ado、ASIAN KUNG-FU GENERATIONに行ったし、2025年も予定が多くある!

第二種電気工事士

令和6年後期試験で合格しました。
免許交付はまだ。

実は前期試験から受けたのですが、実技試験で落ちてしまい...
無事に受かってよかったですね。

久しぶりに試験というものを受けて、プレッシャーを感じる日々でした。
Youtubeを見ながらの試験勉強は現代っぽいなと思っていました。

猫との生活

かわいいね。

2025年初ビビ

写真集

最後に

猫がよろこびます。

www.amazon.jp