Contents
1. 開発環境を整える — macOS と Xcode のインストール手順
1‑1. 対応 macOS バージョンと推奨構成
| 区分 | バージョン | コメント |
|---|---|---|
| 必須 | macOS Ventura (13.0) 以上 | Xcode 14 系の最小要件です。Apple の公式ドキュメントでも同様に記載されています。 |
| 推奨 | macOS Sonoma (14 系) もしくは最新パッチが適用された Ventura | セキュリティとシステム全体のパフォーマンスが向上し、シミュレータや新機能の互換性が高まります。 |
ポイント:Apple Silicon(M1 / M2 系)搭載 Mac では、Xcode のビルド速度が Intel 機に比べて約30 %速くなることが公式ベンチマークで示されています。
1‑2. Xcode の取得方法
| 方法 | 手順 | メモ |
|---|---|---|
| App Store | 1. App Store を開く 2. 「Xcode」で検索 → 「入手」→「インストール」 |
初回は Apple ID が必要です。自動的に最新版(執筆時点では Xcode 15.x)へアップデートされます。 |
| Apple Developer サイト (過去バージョンが必要な場合) | 1. https://developer.apple.com/download/all/ にアクセス 2. Apple ID でサインイン → 「Xcode」→「ダウンロード」 3. .xip ファイルを取得し解凍 → /Applications にドラッグ |
**※ URL は執筆時点のものです。実際のページは developer.apple.com/download/all/ になる可能性がありますので、最終確認してください。 |
| Enterprise / MDM 配布 | 社内向けにカスタムプロビジョニングが必要な場合は、Apple Business Manager 経由で配布できます。 | 大規模開発チームや教育機関で有効です。 |
1‑3. 初回起動と必須設定
- Xcode を起動 → 「Welcome to Xcode」画面が表示されたら Preferences(⌘+,)を開く。
- Locations タブで Command Line Tools が最新バージョンに設定されていることを確認。これで
xcodebuild、swiftコマンドがターミナルから利用可能になります。 - Components 画面で iOS シミュレータ(iOS 17 以降)と macOS Catalyst のパッケージをインストールしておくと、実機がなくても幅広いデバイスでテストできます。
2. SwiftUI 学習の入口 – 公式リソースとおすすめ教材
2‑1. Apple Developer 公式ページ
- URL:https://developer.apple.com/jp/swiftui/get-started/
- 構成
- 「SwiftUI の基本」動画(約15 分) → 基本的な View と Modifier の流れを視覚的に学習。
- ハンズオンプロジェクト(Todo アプリ、Weather App 等) → コードとプレビューが同時に表示されるので、書いた瞬間に結果が確認できます。
注意:上記 URL は執筆時点のものです。Apple がサイト構成を変更した場合は
developer.apple.com/jp/swiftui/以下で最新ページをご確認ください。
2‑2. Zenn の 2024 年版 SwiftUI 入門講座
- URL:https://zenn.dev/rikutosato/books/6cee0a2b8aa796
- 特徴
- 初心者向けに Xcode 14 と Swift 5.9 を前提とした実装例が多数掲載。
- 各章末に「演習問題」や「コードスニペット」のダウンロードリンクがあり、手を動かしながら学べます。
2‑3. 補助教材(書籍・ブログ)
| 種類 | タイトル・リンク | 内容 |
|---|---|---|
| 書籍(2025 年版) | 「Swift 入門ガイド 2025」※出版社公式サイト参照 | 言語仕様から最新ベストプラクティスまで網羅。特に Combine と SwiftUI の連携が詳しい。 |
| 実務ブログ | https://ysinc.co.jp/blog/swift-ios-start/ | 環境構築 → アプリのビルド・テスト → App Store 申請までの実践的フローを解説。 |
| YouTube チュートリアル | 「Apple Developer」公式チャンネル | 毎月更新される WWDC セッションや SwiftUI のライブコーディングが視聴可能。 |
3. SwiftUI の基礎概念と Xcode 15(14)での開発テクニック
3‑1. View・Modifier・Layout の三本柱
| 要素 | 説明 | コード例 |
|---|---|---|
| View | UI の最小単位。Text, Button, Image はすべて View プロトコルに準拠。 |
Text("Hello, SwiftUI") |
| Modifier | View に外観・振る舞いを付与する関数チェーン。順序が描画結果に影響します。 | .font(.title).foregroundColor(.purple) |
| Layout | 複数の View を配置するコンテナ (VStack, HStack, ZStack)。宣言的にレイアウトを記述できます。 |
VStack { … } |
実装サンプル
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
struct IntroSample: View { var body: some View { VStack(alignment: .leading, spacing: 12) { Text("SwiftUI 入門") .font(.largeTitle) .foregroundColor(.blue) Divider() HStack { Image(systemName: "star.fill") .foregroundColor(.yellow) Text("宣言的 UI が楽しい!") } } .padding() } } |
3‑2. 状態管理の基本 – @State と @Binding
| 属性 | 用途 |
|---|---|
| @State | ローカルで変更可能な状態。値が変わると自動的に View が再描画されます。 |
| @Binding | 親ビューから子ビューへ状態を参照渡しする際に使用。子側で更新すると親の @State も反映されます。 |
サンプルコード
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
struct ParentView: View { @State private var isOn = false var body: some View { ToggleView(isOn: $isOn) // $ を付けて Binding に変換 } } struct ToggleView: View { @Binding var isOn: Bool var body: some View { Toggle("スイッチ", isOn: $isOn) .toggleStyle(SwitchToggleStyle(tint: .green)) } } |
3‑3. Xcode のプレビュー活用術(Canvas・ライブインスペクタ)
| 機能 | 操作方法 | 効果 |
|---|---|---|
| Canvas | Option + Command + Return で表示/非表示切替。コード変更ごとに即時反映されます。 |
UI の試行錯誤が高速化。 |
| ライブインスペクタ | プレビュー上の要素をクリック → 右側パネルで属性編集。 | デザイン調整がコードを書き換えずに完了。 |
| シミュレータ連携 | Canvas の下部にあるデバイス選択メニューから任意の iPhone / iPad を指定。 | 実機に近い解像度・入力環境でテスト可能。 |
Tips:
@Environment(\.colorScheme)で Light/Dark モードを切り替え、Canvas のプレビューでも即座に確認できます。
4. ハンズオン実践 – 30 分で完成する Todo アプリ
4‑1. UI 設計とコンポーネント一覧
| 画面 | 主な SwiftUI コンポーネント |
|---|---|
| タスク一覧 | NavigationView → List(ForEach と $todos) |
| タスク追加シート | Sheet + Form → TextField、Button |
| 完了切替 | Toggle(カスタム CheckboxToggleStyle) |
4‑2. 完全コード
(1) データモデルと永続化インターフェース
|
1 2 3 4 5 6 7 8 |
import Foundation struct Todo: Identifiable, Codable { let id = UUID() var title: String var isDone: Bool = false } |
(2) UserDefaults を利用した保存・読込拡張
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
extension UserDefaults { private static let todosKey = "todos" func save(_ todos: [Todo]) { if let data = try? JSONEncoder().encode(todos) { set(data, forKey: Self.todosKey) } } func loadTodos() -> [Todo] { guard let data = data(forKey: Self.todosKey), let decoded = try? JSONDecoder().decode([Todo].self, from: data) else { return [] } return decoded } } |
(3) メインビュー
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
import SwiftUI struct ContentView: View { @State private var todos: [Todo] = [] @State private var showingAdd = false var body: some View { NavigationView { List { ForEach($todos) { $todo in HStack { Toggle(isOn: $todo.isDone) { Text(todo.title) .strikethrough(todo.isDone, color: .gray) } .toggleStyle(CheckboxToggleStyle()) } } .onDelete(perform: delete) } .navigationTitle("Todo") .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button(action: { showingAdd = true }) { Image(systemName: "plus") } } } .sheet(isPresented: $showingAdd) { AddTodoView(todos: $todos) } .onAppear { todos = UserDefaults.standard.loadTodos() } .onChange(of: todos) { UserDefaults.standard.save($0) } } } private func delete(at offsets: IndexSet) { todos.remove(atOffsets: offsets) } } |
(4) タスク追加シート
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
struct AddTodoView: View { @Binding var todos: [Todo] @Environment(\.dismiss) private var dismiss @State private var newTitle = "" var body: some View { NavigationView { Form { TextField("タスク名を入力", text: $newTitle) Button("追加") { guard !newTitle.isEmpty else { return } todos.append(Todo(title: newTitle)) dismiss() } .disabled(newTitle.isEmpty) } .navigationTitle("新規タスク") .toolbar { ToolbarItem(placement: .cancellationAction) { Button("キャンセル") { dismiss() } } } } } } |
(5) プレビュー
|
1 2 3 4 5 6 |
struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } } |
4‑3. デバッグとテストのポイント
| 手順 | 方法 |
|---|---|
| Canvas で即時確認 | ContentView のコードを書き換えるたびに Canvas が自動リロードされるので、UI の微調整が瞬時に可能です。 |
| シミュレータ実行 | Xcode ツールバー → デバイス選択(例:iPhone 15 Pro, iOS 17) → ⌘R でビルド・実行。タップ操作やキーボード入力が正しく反映されるか検証します。 |
| コンソール出力 | print("Todo count: \\(todos.count)") を追加し、Debug > Open Console でリアルタイムに状態変化を確認できます。 |
まとめ:この Todo アプリは View・Modifier・State の基本だけで完結します。実装がシンプルな分、デバッグや拡張(リマインダー通知、CoreData 永続化)もスムーズに行えます。
5. 次のステップ – データ永続化と UIKit 併用
5‑1. Core Data・CloudKit への移行戦略
| フェーズ | 実装例 |
|---|---|
| 簡易保存 | 上記 UserDefaults 拡張でローカルに JSON 保存。小規模アプリやプロトタイプ向け。 |
| 本格永続化 | @FetchRequest(entity: TodoEntity.entity(), sortDescriptors: []) と組み合わせ、NSPersistentContainer を AppDelegate または PersistenceController に配置。 |
| クラウド同期 | CloudKit のパブリッシュ・サブスクライブ機能を利用し、複数デバイス間で Todo データを自動同期。 |
注意:Core Data はスキーマ変更時にマイグレーションが必要です。開発初期段階から
NSPersistentContainerを用意しておくと後の拡張が楽になります。
5‑2. UIKit コンポーネントを SwiftUI に組み込む
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import SwiftUI import UIKit struct CalendarWrapper: UIViewRepresentable { func makeUIView(context: Context) -> UIDatePicker { let picker = UIDatePicker() picker.preferredDatePickerStyle = .inline return picker } func updateUIView(_ uiView: UIDatePicker, context: Context) { // 必要に応じてプロパティ更新(例:最小日付・最大日付) } } |
- 利用シーン
- カレンダーやマップなど、SwiftUI にまだ完全移行されていない高度な UIKit ウィジェット。
- 既存の Objective‑C/UIKit ライブラリを段階的に SwiftUI プロジェクトへ統合したい場合。
5‑3. 学習ロードマップ(推奨順)
- 環境構築 & 基礎 View → 本稿で学んだ Todo アプリ完成。
- 状態管理の応用 (
@ObservedObject,@StateObjectと Combine)→ データフローを整理。 - 永続化 → UserDefaults → Core Data → CloudKit の順に実装練習。
- 高度 UI → カスタム
UIViewRepresentable、Canvasでの描画、GraphicsContextを活用したアニメーション。 - App Store 配布 → プロビジョニングプロファイル作成、TestFlight テスト、リリース手順。
6. まとめ
- macOS Ventura 以上+Xcode 14/15 が揃っていれば、SwiftUI の開発はすぐに始められます。
- Apple の公式チュートリアルと Zenn の実装例を組み合わせることで、理論とハンズオンがバランスよく学べます。
- 本稿の Todo アプリは View・Modifier・State の三要素だけで完結し、30 分程度で完成できるため、学習の入口として最適です。
- 永続化や UIKit 併用といった次段階へは、段階的に Core Data や
UIViewRepresentableを導入するとスムーズです。
最後に:リンク先は執筆時点で確認したものですが、Apple のサイトは頻繁に更新されます。実際にダウンロードやドキュメント閲覧を行う前に、公式ページの URL が最新かどうか必ずご確認ください。