[iOS] MVVMアーキテクチャ

– Model:データ構造(ToDoアイテム)
– ViewModel:データ管理・ロジック
– View:UI(ユーザーが触れる部分)

ディレクトリ構成
MVVMToDoApp/
├── Models/
│ └── Todo.swift
├── ViewModels/
│ └── TodoViewModel.swift
└── Views/
└── ContentView.swift

### Model
Todo.swift

import Foundation

struct Todo: Identifiable, Codable {
    let id = UUID()
    var title: String
    var isCompleted: Bool = false
}

### View

//
//  ContentView.swift
//  CoreDataTest
//
//  Created by mac on 2025/10/25.
//

import SwiftUI

struct ContentView: View {
    @StateObject private var viewModel = TodoViewModel()
    @State private var newTodoTitle = ""
    
    var body: some View {
        NavigationView {
            VStack {
                HStack {
                    TextField("新しいタスクを入力", text: $newTodoTitle)
                        .textFieldStyle(RoundedBorderTextFieldStyle())
                    
                    Button(action: {
                        viewModel.addTodo(title: newTodoTitle)
                        newTodoTitle = ""
                    }) {
                        Image(systemName: "plus.circle.fill")
                            .font(.title2)
                    }
                }
                .padding()
                
                List {
                    ForEach(viewModel.todos) { todo in
                        HStack {
                            Image(systemName: todo.isCompleted ? "checkmark.circle.fill" : "circle")
                                .foregroundColor(todo.isCompleted ? .green : .gray)
                                .onTapGesture {
                                    viewModel.toggleCompletion(for: todo)
                                }
                            Text(todo.title)
                                .strikethrough(todo.isCompleted)
                        }
                    }
                    .onDelete(perform: viewModel.deleteTodo)
                }
            }
            .navigationTitle("ToDoリスト")
        }
    }
}

### ViewModels

import Foundation

class TodoViewModel: ObservableObject {
    @Published var todos: [Todo] = []
    
    func addTodo(title: String) {
        guard !title.isEmpty else { return }
        let newTodo = Todo(title: title)
        todos.append(newTodo)
    }
    
    func toggleCompletion(for todo: Todo) {
        if let index = todos.firstIndex(where: { $0.id == todo.id }) {
            todos[index].isCompleted.toggle()
        }
    }
    
    func deleteTodo(at offsets: IndexSet) {
        todos.remove(atOffsets: offsets)
    }
}

main

import SwiftUI

@main
struct MVVMToDoApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

なるほど〜