こんにちは、DevRelブロックのikkouです。2024年8月22日の夕方から24日の3日間にわたり「iOSDC Japan 2024」が開催されました。ZOZOは昨年同様プラチナスポンサーとして協賛し、スポンサーブースを出展しました。
本記事では、前半は「iOSエンジニアの視点」から、ZOZOから登壇したセッションとiOSエンジニアが気になったセッションを紹介します。そして後半は「DevRelの視点」から、ZOZOの協賛ブースの様子と各社のブースコーデのまとめを写真多めでお伝えします。
登壇内容の紹介
今年のiOSDCではLTに1名、ポスターセッションに1名、パンフレット寄稿に3名が採択されました。会場で発表されたLTとポスターセッションについて紹介します。
LT: 全力の跳躍を捉える計測アプリを作る
新卒3年目にして連続登壇3年目となるiOSエンジニアのおぎじゅんは、昨年・一昨年の「疾走」から「跳躍」にテーマを変えてトークを披露しました。手拍子まじりで進められるLTはおぎじゅんならではの非常に勢いがあるものだったのではないでしょうか。
このLTの背景や苦労話は個人ブログに詳しくまとめられているので、あわせてご覧ください。
おぎじゅんからのコメント
今年は大トリということでプレッシャーを感じていましたが、全力で楽しく発表できました! 皆さんの頭の中に少しでも残るLTになっていたら幸いです。
ポスターセッション: Haptic Feedbackでクセになるユーザー体験を提供しよう!
新卒1年目のiOSエンジニアであるイッセーは、Haptic Feedbackに関するポスターセッションを行いました。期間中、各日1時間をコアタイムとしてポスターの前に立ち、来場者とのコミュニケーションを楽しんでいました。Haptic Feedbackはその特性上、実際に触ってみることで理解が深まるため、iPhone実機に触れてもらいながら説明できるポスターセッションは非常に有効な手法でした。
イッセーからのコメント
今年4月に新卒入社し、初めて登壇の機会をいただきました。参加者の皆様とポスターを見ながらお話しする中で、Haptic Feedbackに関する知見をさらに深めることができました。足を運んでいただいた皆様、ありがとうございました。
ZOZOのiOSエンジニアが気になったセッションの紹介
Server-Driven UI入門: 画面のStateを直接受け取るアプローチ by nade
ZOZOTOWN開発本部iOSブロック1内定者アルバイトのだーはまです。nadeさんの「Server-Driven UI入門: 画面のStateを直接受け取るアプローチ」が個人的にかなり良かったので紹介します!
Server-Driven UI (以下:SDUI) を初めて耳にする方もいると思います。SDUIとは、事前に定義されたUIコンポーネントのLayout/State/Actionをサーバーからレスポンスとして返すというコンセプトをもとにした開発設計です。クライアント側で実装していたUIロジックを(クライアントではなく)サーバーに押し込むような設計となっており、SDUIを導入することで開発工数やクライアントからのリクエスト数などを削減でき、開発スピードの向上が見込めます。
トークの構成は3部制(入門、番外、応用)となっていて、SDUIの基礎から実践までを網羅的に学べます。特に、応用編で述べられていた既存アプリ(タップル)へSDUIを導入する話は、SDUI導入を検討しているエンジニアにとっては必見です。
下記は個人的に重要だと感じたトーク内容をまとめています。
nadeさんは、SDUIのコンセプトを3つの参考記事から紐解いています。
- WWDC 2010:Building a Server-Driven User Experience
- Spotify 2016:Backend-driven native UI
- AirBnB2021:A Deep Dive into Airbnb’s Server-Driven UI System
WWDC 2010は、サーバーからクライアントへUI Componentのプロパティごと返却することで開発の柔軟性をあげようという思想のもと発表されたようです。
上記3つの記事から導かれたSDUIのコンセプトは、”事前に定義されたUIコンポーネントのプロパティを含めてサーバーから返却すること”です。
以下に示すようUIコンポーネントのデータが含まれたJSONを、クライアントはサーバーから受け取ります。また、swiftではCodableによってJSONをstructへ簡単に変換できます。これを用いてJSONデータをSwiftUI.view(Struct)へ変換しUIを構築します。
{ "screens": [ { "id": "ROOT", "layout": { "wide": {}, # landscape mode "compact": { # portrait mode "type": "SingleColumnLayout", # レイアウトの種類 "main": { "type": "MultipleSectionsPlacement", "sectionDetails": [ # 画面要素のsectionIdのみ { "sectionId": "hero_section" }, { "sectionId": "title_section" } ] } } } } ] }
{ "sections": [ { "id": "toolbar_section", "sectionComponentType": "TOOLBAR", "section": { "type": "ToolbarSection", "nav_button": { "onClickAction": { # タップ時のアクション "type": "NavigateBack", "screenId": "previous_screen_id" } } } }, { "id": "hero_section", "sectionComponentType": "HERO", "section": { "type": "HeroSection", "images": [ # HeroSectionコンポーネントのState、typeごとに型が違う "api.hoge.com/..." ] } } ] }
メリットとデメリットは以下の通りです。
- メリット
- 画面構成を変更するたびにアプリの審査やリリースする必要がなくなる
- iOS,Androidで開発している場合、これまでは画面に関するロジックを2つ(iOS,Android用)書く必要があったが、統一可能となる
- トーク中、nadeさんからモバイル(iOS,Android)の開発において同じロジックをOS毎に分けて書いているのは、DRY原則(Don't repeat yourself=繰り返しを避けろ)になるのではと話されていて、モバイル開発の問題をついていて面白いなと思いました。
- サーバーへのリクエスト数を減らせる
- これまでは、1画面を作るのに画面を組み立てるために”プロパティを得るため複数回のリクエスト”を送っていました。しかし、SDUIではサーバーからプロパティ込みでレスポンスがあるので、複数回リクエストする必要がなくなり、リクエスト数を減らせます。
- デメリット
- 事前のUIコンポーネント定義や基盤構築が大変
- クライアントーバックエンドのスキルを併せ持つ人材が必要
- BFFを書けるクライアントエンジニア + UIのStateを適切に考えられるバックエンドエンジニア
- 属人性が高くなる
システムの境界を引く位置が既存の開発手法と異なるというSDUIの性質を応用して、nadeさんは境界の位置を調整した軽量SDUIを提案しています。軽量SDUIは、全てのUIロジックをサーバーに移行するのではなくシステム運用可能性の高いものだけを限定して譲渡する設計です。
例: タップルの検索機能
layoutはクライアントが担当し、state,actionをバックエンドが担当する。そして、SwiftUI.viewにStateを定義し、そのままバックエンドから受け取る。つまり、layout/state/action全てをバックエンドに渡すのではなく、特定のstate/actionのみを渡す、これが軽量化されたSDUI、軽量SDUIです。FatVIewではなく状態管理が適切に行われているプロジェクトであれば、SDUIの導入も比較的容易だと思います。
KMPと似ていてロジックを共通化して開発効率をあげようという設計、面白いです。
watchOS 最前線 〜現代のApple Watch向けアプリの作り方〜 by kouki_dan
ZOZOTOWN開発本部iOSブロック1のだーはまです。kouki_danさんの「watchOS 最前線 〜現代のApple Watch向けアプリの作り方〜」がApple Watch開発のキャッチアップとしてとても参考になったので紹介します。
本トークでは、Apple Watch(以下:Watch)アプリ実装に関するTipsが紹介されています。トークを聞くことで、Watchアプリの実装イメージが具体化され、開発してみようと(重い腰)を上げられるようになるはずです。kouki_danさんが個人で開発している2つのアプリを例として話が進むため、実践的で分かりやすいトークでした。
トークを聞き、個人的に納得したのがiPhoneとWatchではUXが異なるという点です。iPhoneは操作を画面と指で行うのに対して、Watchは画面と指に加えてDigital Crownも用います。また、画面サイズも小さいです。そのため、ユーザーがアプリを使う場面や操作方法が異なり、Watch独自のユースケースを考える必要があります(だーはまの声:何かZOZOでもWatchアプリ作れないかな…)。
WatchアプリはSwiftUIと実装コードが非常に似ているため、SwiftUI触ったことある人なら比較的簡単に実装できると思います。しかも、iPhoneに比べて画面サイズが小さいため、実装工数も少ないです。
下記で、Watchアプリ実装のTipsを紹介していきます。
- TabView : タブ表示が可能となる
- モディファイア.tabViewStyle(.verticalPage) によって、Digital Crownのスクロール方向を指定可能です。実装をみてわかるように、VStack, Image, TextなどSwiftUIをそのまま流用できる箇所が多くあります。
// MARK: - TabView TabView { VStack { Image(systemName: "globe") .imageScale(.large) .foregroundStyle(.tint) Text("Tab1") } VStack { Image(systemName: "globe") .imageScale(.large) .foregroundStyle(.tint) Text("Tab2") } List(0..<20) { Text("Item \($0)") } } .tabViewStyle(.verticalPage)
- TimelineView : 時間経過によって変化するViewの描画に使う
- contextが時間経過とともに変化していき、
Circle()
を再描画させます。
- contextが時間経過とともに変化していき、
TimelineView(.animation) { context in let elapsedTime = context.date.timeIntervalSince(start) ZStack { Circle() .stroke(Color.gray, lineWidth: 20) Circle() .trim(from: 0, to: elapsedTime / 60) .stroke(Color.green, lineWidth: 20) .rotationEffect(.degrees(-90)) Text(String(format: "%.2f", max(0, 60-elapsedTime))) .monospacedDigit() .font(.title) } }
- .difitalCrownRotation(_:) : デジタルクラウンの回転状況を検知可能
- デフォルトでは回転方向が縦になっています。
Text("\(rotation, specifier: "%.1f")") .focusable() .digitalCrownRotation($rotation)
- .scenePadding(_:) : paddingの指定が可能となる。
- Watchは画面が小さく、また角丸になっているため、paddingが重要になってきます。この
.scenePadding(_:)
を指定しないとpaddingがなくなり、コンポーネントが見切れてしまう可能性あります。
- Watchは画面が小さく、また角丸になっているため、paddingが重要になってきます。この
トーク内では、上記以外の実装についても触れられています。気になる方はスライドやアーカイブをチェックしてみてください。
Watchアプリの実装について網羅的に知れるとても有意義なトークでした! iOSDCではトーク後5分間のディスカッションの時間が設けられています。僕が実際質問したことを書いて、このトークの紹介を終わりにしたいと思います。
Q. iPhoneとWatchではUXがかなり異なると思うが、参考にするべきサイトやアプリはありますか? A. Appleが出しているWatchアプリ
今後Watchアプリを開発しデザイナーと話す際、思い出して参考にしたいと思います。
Accessibility for Swift Charts 〜 by Mika Ito
FAANS部フロントエンドブロックiOSエンジニアのましょーです。私は、Mikaさんの「Accessibility for Swift Charts」についてご紹介します!
このセッションは、目の見えない、見えにくい方のために、Swift Chartsで作成されたグラフのデータをVoiceOverやAudio Graphsを用いて音で表現してみたという内容でした。日経平均株価の折れ線グラフを音で表現したり、グラフを音にしたりしてみると音楽になっていたりと、とても面白く、惹きつけられるセッションでした。
まず、このセッションで利用されているSwift Charts、VoiceOver、Audio Graphsについて紹介します。Swift ChartsはSwiftUIを用いて折れ線グラフ、散布図などのグラフを作成できるフレームワークです。また、VoiceOverとは、グラフのデータにカーソルを合わせると値を読み上げてくれる機能です。歩数計だと「〇〇年〇月 歩数 1日平均〇〇歩」のように読み上げてくれるようです。Audio Graphsはグラフのデータを音声に変換する機能です。こちらはVoiceOverとは異なり、文章ではなく音の高低でデータを表現します。
このセッションではSwift Chartsで作成されたデータをVoiceOverやAudio Graphsでいかに読み上げるかについて言及しています。前提としてSwift ChartsはVoiceOverやAudio Graphsを自動サポートしているようです。例えば、以下のようなプログラムでグラフを生成したとします。
struct Climate: Identifiable { var id: UUID = .init() var month: Int var precipitation: Double } var body: some View { Chart { ForEach(data, id: \.id) { item in BarMark( x: .value("Month", item.month), y: .value("Precipitation", item.precipitation) ) } } .chartXAxisLabel("月") .chartYAxisLabel("降水量") ... }
上記のプログラムでは、月ごとの降水量を棒グラフで表示しています。この棒グラフをVoiceOverやAudio Graphsで読み上げてみると、以下のような問題が発生します。
- 単位が読み上げられないため、何の値かわかりにくい(VoiceOver)
- 降水量はDoubleなのに小数点以下が読み上げられていない(VoiceOver)
- 例えば7月のデータをタップした際に「7to8」のように読み上げられてしまう(VoiceOver)
- 「X軸はMonthです、Y軸はPrecipitationです」のように各軸が英語で説明される(Audio Graphs)
これらの問題を解決するためにMikaさんは次のような変更をプログラムに加えていました。
var body: some View { Chart { ForEach(data, id: \.id) { item in BarMark( x: .value("月", item.month), y: .value("降水量", item.precipitation) ) .accessibilityLabel("\(item.month) 月") .accessibilityValue("\(String(format: "%.1f", item.precipitation)) ミリメートル") } } .chartXAxisLabel("月") .chartYAxisLabel("降水量") ... }
上記のように、単位の追加やラベルを日本語に修正するなどの変更を加えることで先述の問題点を解決でき、意図した読み上げを行えるようです。音を用いてデータを伝える場合には、データがどのように読み上げられるか、聞き手に正しく伝わるかを考慮して、プログラムを作成する必要があると感じました。
本セッションを聞いて、データを音で表現することにとても興味が湧きましたし、たくさんの可能性を感じました! 私の開発しているFAANSでも、コーデの売上や送客数などをグラフで表現しているため、アクセシビリティ対応の一環としてデータの読み上げ機能を実装してみたいと思います!
健康第一!MetricKitで始めるアプリの健康診断
ZOZOTOWN開発本部 iOSブロックの@tsuzuki817です! 自分からはnekowenさんの「健康第一!MetricKitで始めるアプリの健康診断」をご紹介いたします!
iOSアプリのパフォーマンス改善の指標は以下の4つです。
- 応答性
- タップやジェスチャーに対してアプリがどのくらいの速度で応答するか
- アプリの起動時間
- ユーザーがアプリアイコンをタップしてから起動するまでの時間
- メモリの使用量
- アプリがデバイスのメモリを利用している使用量
- バッテリー効率
- デバイスのバッテリーの持ちを良くする
またパフォーマンス情報の収集の方法として3つ挙げられておりました。
- Xcode Organaizer
- 設定不要(XcodeのOrganizerで確認できる)
- 基本的なパフォーマンスデータが可視化できる
- TestFlightでは集計されない
- MetricKit
- 要実装(比較的簡単)
- 収取したデータをCrashlyticsなどに集約できる
- カスタムイベントの追加が可能
- Firebase Perfomance Monitoringなどの外部サービス
- SDKの導入だけで自動的に収集される
- カスタムイベントの追跡が可能
- 詳細なパフォーマンスデータは取れない
それぞれに長所・短所があるので各々のプロダクトに見合った計測方法の検討が必要です。
パフォーマンス情報で見ておくべき観点は以下の3つです。
- アプリの起動時間が伸びていないか
- アプリがシステムによって終了されていないか
- アプリがフリーズしていないか
アプリの起動時間は今回のiOSDCの他のセッションでも度々挙げられており、さまざまなシーンでアプリが普及している現代ではかなり重要度が上がっていると思います。
MetricKitの情報はFirebaseのCrashlyticsに一緒に送ることができます。実例でCrashlytics、TestFlightにクラッシュログが落ちていないクラッシュをMetricKitを使って事前に検知する仕組みを導入しており、目に見えにくいかつ他ツールではハンドリングが難しいクラッシュの把握に役立つことがわかりました。
アプリも人間も健康第一だと思います。アプリの健康診断の項目を適切に考え、より良いアプリを作り続けていくための仕組みづくりを整えていきたいと思わせてくれる素晴らしいセッションでした!
Apple Siliconを最大限に活用する方法
ZOZOTOWN開発本部 iOSブロックの@tsuzuki817です! 自分から@EXCode013さんの「Apple Siliconを最大限に活用する方法」をご紹介いたします!
Apple Siliconのスマートフォン、PC、スマートウォッチを使っているのにApple Siliconのパワーを最大限に活用しないのは勿体無いと思いセッションを聞かせていただきました!
CoreMLを使うことでApple SiliconのNeural Engineのパワーを引き出すことができるそうです。CoreMLと聞くと一見難しそうでしたが、CoreMLを動かす上位のフレームワークである以下のようなフレームワークを使うことでも良いとのこと!
- Vision
- Neural Language
- Speech
- Sound Analysis
CoreMLでモデルを作る前にこちらのフレームワークで事足りるか調査すると良さそうですね!
また、AccelerateフレームワークはApple Siliconのパワーを引き出しつつ簡単に使いやすいよう抽象化されたAPIになっており既存の処理でも高速化できそうだなと思えました。その中でも一番使っていて効果が出そうだなと思ったのはvImage
を使った画像処理です。
実際にセッション中にデモをしていただいたのですが、画像処理の代表と言っても過言ではないCIFilterとvImage
を使って画像にブラーをかける処理を行いました。vImage
はCIFilterを使ったブラー処理よりも1.5倍ほど処理が速く、大量にCIFilterをかける処理を書いているケースなどではさらに効力を発揮するのではないかと思いました。
Ask The SpeakerでvImage
を使った画像処理のコードを読ませてもらったのですが、Metalのような複雑な処理は特にいらずに書かれており学習コストはそこまで高くないと感じました。デモに使ったコードはそのうち公開してくれるらしいので楽しみにしています!
ZOZOブースの紹介
会期中は15名以上のZOZOスタッフが入れ替わりながらブースに立っていました。今回、ZOZOブースでは今年5月にリニューアルした「WEAR by ZOZO」の「ファッションジャンル診断」をメインコンテンツとして展示していました。
この「ファッションジャンル診断」は、WEARに投稿されている好みのコーディネートを5枚以上選ぶことで、AIがファッションジャンルを診断し、おすすめのコーデを教えてくれる機能です。
ブースに訪れた方々には、お手元のiPhoneまたデモ用のiPhoneでこの「ファッションジャンル診断」を体験してもらいました。
この「ファッションジャンル診断」はWEARでいつでも体験できる機能ですが、ブースで体験または診断結果を見せてくれた方には、その診断結果にあわせた診断結果ステッカーをお渡ししました。ステッカーの種類は全部で144種類! 名札に入れてもらったり、お手持ちのiPhoneに貼ってもらったり、皆さんそれぞれの使い方で楽しんでいました。
もっとも多かったジャンルは「リラックスしがちなシンプル」で、次点に「少々スッキリしたラフ」そして「少々スッキリしたストリート」と続きました。また、当初の予想に反して意外と多かったのは「少々アクティブなシンプル」と「少々スッキリしたアウトドア・スポーツ」でした。ちなみに私は「リラックスしがちなシンプル」です!
その他、昨年制作したZOZOTOWNのキャラクターである「箱猫マックスくん」のステッカーは新作を交えて配布しました。このステッカーはLINEスタンプで「箱猫マックス Vol.6」として配信しているものです。エンジニア間のコミュニケーションに使いやすいスタンプが揃っているので、ぜひ使ってみてください!
また、デザイナー発案の「洒落の効いたアイテム」として「“一合一会”米」や「“失敗を水に流す”トイレットペーパー」に続き、今年は参加者の皆さんとの「縁」を結ぶ「色“縁”ぴつ」を作成しました。こちらは特定の条件を満たした方にお渡ししていました。
今年もとても多くの方にブースを来訪していただき、ZOZOの取り組みやサービスに興味を持っていただけたようで、とても嬉しく思います。また、ZOZOスタッフも多くの方とお話しでき、楽しい時間を過ごすことができました。会期の直前に「ZOZOのiOSエンジニアに興味をお持ちの方へ 」を公開したこともあり、プロダクトごとの技術スタックの違いなどもご説明できて良かったです。来年もZOZOブースで皆さんとお会いできることを楽しみにしています!
協賛企業ブースのコーデまとめ
あっすーです。iOSDC Japan 2024の協賛企業ブースを回ってきましたので、各ブースのコーデをお送りします!
各社の雰囲気に合わせたデザイン・着こなしは、やはりZOZOとしても気になるポイント。当日の会場の様子を思い出しながらご覧ください。
スポンサーブースA(1F)
スポンサーブースB(1F)
スポンサーブースC (2F展示ルーム)
スポンサーブースD (1Fコミュニティスペース)
Tシャツスポンサー
こうやって並べてみると各社の雰囲気がわかりますね。色の傾向としてはやはり黒と白が多かったです。お忙しい中ご協力いただいたブースの皆さん、本当にありがとうございました!
アフターイベントを開催します
締めの前に告知です! iOSDC Japanは参加レポート記事を書く#iwillblog
文化がありますが、それと同じくらいアフターイベント文化も活発です。観測する今年は限り9つのiOSDC関連アフターイベントが催されます。私たちもそのひとつとしてマネーフォワードさんと非公式の合同イベント「iOSDC Japan 2024 After Talk」を9月10日(火)19時より開催いたします。
ZOZOからはLTに登壇したおぎじゅん、ポスターセッションに登壇したイッセーが登壇する他、協賛やブース運営に関してDevRel文脈のパネルディスカッションも予定しています。YouTubeを視聴するオンライン形式となりますので、connpassに参加登録の上、お気軽にご視聴ください! わいわいしましょう!
おわりに
ZOZOは毎年iOSDC Japanに協賛し、ブースを出展していますが、多くの方との交流を通して今年も最高の3日間を過ごせました。実行委員会の皆さんに感謝しつつ、来年もまた素敵な時間を過ごせることを楽しみにしています!
ZOZOでは、来年のiOSDC Japanを一緒に盛り上げるエンジニアを募集しています。ご興味のある方はこちらからご応募ください。
また、会期中は混雑していることも多く、じっくりとお話しする時間が取れなかったので、もう少し詳しく話を聞きたい! という方はカジュアル面談も受け付けています。
それではまた来年のiOSDC Japanでお会いしましょう! 現場からは以上です!