Mima Design MemottoWEB DESIGNER · mima

SwiftUIでカスタムリストビューを作るステップバイステップ

SwiftUIは、iOSアプリ開発におけるUI構築の常識を大きく変えました。宣言的な構文とライブプレビューのおかげで、かつて大量のコードが必要だった画面が、驚くほどシンプルに書けるようになっています。その中でも、リスト表示は多くのアプリに欠かせない要素であり、実装の仕方でユーザー体験が大きく変わります。

私自身、Webデザイナーとしての経験を活かしてモバイルアプリの世界に飛び込み、最初に驚いたのがListやForEachの組み合わせの柔軟さでした。UITableViewの時代を知っていれば、SwiftUIのリストがどれだけ直感的かを実感できるはずです。本記事では、自分の手でカスタムリストビューを作り上げる流れを、一つずつ丁寧に追っていきます。

XcodeとSwiftの基本的な知識があれば十分です。サンプルコードをそのまま書き写すだけでなく、なぜその書き方をするのかを意識しながら読み進めていただくと、後々の応用が効きやすくなります。

プロジェクトの土台を整える

まずはXcodeで新しいプロジェクトを作成し、SwiftUIのテンプレートを選びます。プロジェクト名は何でも構いませんが、ここでは「CustomListDemo」とでもしておきましょう。作成したらContentView.swiftを開き、不要なデフォルトコードを削除して、白紙のキャンバスを作ります。

次に、ナビゲーションの土台としてNavigationStackを用意します。最新のSwiftUIではNavigationViewよりもNavigationStackを使う方が推奨されており、iOS 16以降の標準的な書き方になります。タイトル表示や遷移の管理がしやすくなるため、最初にこの構造を整えておくと後工程が楽になります。

データ管理には、可能なら@StateObjectや@ObservedObjectを使って外部の状態と接続する設計をおすすめします。今回はサンプルとして、後で差し替えやすいシンプルなObservableObjectを用意し、そこにリストに表示するデータを持たせる形にします。

データモデルの設計

リストに表示する内容を構造化するために、Identifiableプロトコルに準拠したモデルを作ります。例えば、旅行の記録を一覧表示したい場合は、行き先、訪問日、写真の評価といった項目をまとめて扱うstructを定義します。Identifiableに準拠することで、SwiftUIのListは各行を一意に識別でき、アニメーションや差分更新が正しく動作します。

モデルはシンプルに保つのが鉄則です。表示用の整形済み文字列や、Viewから組み立てるような複雑な構造はモデルに持たせず、別途フォーマッタや変換メソッドを切り出します。こうすることで、モデルのテストが書きやすくなり、将来CoreDataやRealmに切り替える際にも影響範囲を限定できます。

サンプルとして作成したモデルは、後でフィルターや並び替えの機能を追加するため、Comparableに準拠させておくと便利です。ハッカソンや勉強会でSwiftUIを教える際も、このモデル設計の段階から丁寧に説明すると、参加者の理解度がぐっと上がります。

ListとForEachの基本を理解する

Listは内部的にUITableViewをベースに作られていますが、書き方は圧倒的に短くなりました。単純に配列を表示したいだけなら、Listの中にForEachをネストするだけで十分です。静的・動的な要素を混在させたい場合、ForEachを独立させて使うことで柔軟性が増します。

ここで、一つ意識したいのは、リストの行が再描画されるタイミングです。Identifiableなidが正しく設定されていれば、行の追加・削除・並び替えが滑らかなアニメーションで動きます。逆にidが重複していたり不安定な値を返したりすると、パフォーマンスが落ちたり意図しない再描画が起きたりします。

Web制作の経験がある方なら、Reactのkey propと似た概念だと考えるとわかりやすいでしょう。SwiftUIでもkeyとなる識別子を安定して供給することが、気持ちのいい動作の基本になります。

カスタムセルで世界観を演出する

Listのデフォルトの行はシンプルで便利ですが、アプリの世界観を表現するには物足りません。HStackやVStack、Spacer、Imageを組み合わせれば、オリジナルのセルを自由にデザインできます。例えば、左にサムネイル、中央にタイトルとサブタイトル、右に評価星を並べるといったレイアウトも、数行で書けてしまいます。

ここで、私がよく使う小技を一つ紹介します。セルの高さを揃えたいときは、.frame(maxWidth: .infinity, alignment: .leading)や固定値の高さを指定します。複数行のテキストが入る場合は.lineLimitを設定し、省略記号の扱いもコントロールできます。Dividerを間に挟むことでリスト全体にリズムが生まれます。

デザインの細部にまでこだわれるのは、SwiftUIの強みです。Webで磨いた感覚をモバイルに持ち込むことで、自分らしいUIを作れる楽しさを改めて実感できます。

スタイルとアニメーションを加える

基本のリストが動くようになったら、見た目を整えていきます。.listStyle(.plain)や.insetGrouped、.sidebarなど、利用シーンに応じて切り替えられるスタイルが標準で用意されています。CardViewのように見せたい場合は、ScrollViewとLazyVStackを組み合わせる選択肢もあります。

アニメーションは、withAnimationブロックと組み合わせることで効果が高まります。例えば、フィルターを切り替えたとき、リストの並び順を滑らかに変化させることができます。アニメーションのパラメータを微調整するだけで、アプリの質感が大きく変わるのも面白いところです。

ハッカソンでは、短時間でUIを作りつつも、ほんの少しの動きを加えるだけで審査員の目を引けることがあります。SwiftUIのアニメーションは、少ないコードで見栄えを底上げできる頼もしい味方です。以前取り組んだブログエンジン自作のような別言語の案件でも、同じ思想で作り込むことが多いです。

つまずきやすいポイントと対策

初心者がよく詰まるのは、プレビューがクラッシュするケースです。多くの場合、@Stateや@StateObjectの初期化方法に問題があるか、ナビゲーションの遷移先で参照が切れていることが原因です。エラーメッセージを丁寧に読み、関連する行を一つずつ確認していくのが解決の近道です。

もう一つの落とし穴が、List内のButtonやNavigationLinkが思うように動かないという問題です。これは、タップ領域の確保やジェスチャの競合が原因になっていることが多く、Buttonのスタイルをリセットしたり、NavigationLinkを専用の形式に置き換えたりすることで解決できます。

自分で作っているときは気づきにくいバグも、勉強会で仲間に触ってもらうと一瞬で発見されることがあります。独学とコミュニティの活用を両立させることが、上達への近道だと感じています。


SwiftUIのカスタムリストビューは、一度仕組みを理解してしまえば、さまざまな画面に展開できる強力なパターンです。アプリ全体のユーザー体験を支える重要な要素なので、ぜひ手を動かして試してみてください。最新の活動や他の制作事例はポートフォリオサイトからたどれます。コメントやリクエストもお待ちしています。