【Xcode/SwiftUI】ポケモンリストを作ってUserDefaultsを学ぶ

実装

Model

import Foundation

struct Pokemon: Codable, Identifiable {
    var id: Int
    var name: String
    var type: String
    var level: Int

    init(id: Int, name: String, type: String, level: Int) {
        self.id = id
        self.name = name
        self.type = type
        self.level = level
    }

}

UserDefaults

import SwiftUI

class PokemonStore: ObservableObject {
    @Published var pokemons: [Pokemon] {
        didSet {
            let encoder = JSONEncoder()
            if let encoded = try? encoder.encode(pokemons) {
                UserDefaults.standard.set(encoded, forKey: "pokemons")
            }
        }
    }

    // UserDefaultsから情報を取得する
    init() {
        if let savedData = UserDefaults.standard.data(forKey: "pokemons") {
            let decoder = JSONDecoder()
            if let loadedData = try? decoder.decode([Pokemon].self, from: savedData) {
                pokemons = loadedData
                return
            }
        }
        pokemons = []
    }
}

HomeView.swift (メインのView)

import SwiftUI

struct HomeView: View {
    var body: some View {
        PokemonListView()
            .environmentObject(PokemonStore())
    }
}

struct HomeView_Previews: PreviewProvider {
    static var previews: some View {
        HomeView()
    }
}

PokemonListView.swift (ポケモンのリストを表示)

import SwiftUI

struct PokemonListView: View {
    @EnvironmentObject var pokemonStore: PokemonStore

    var body: some View {
        NavigationView {
            List(pokemonStore.pokemons) { pokemon in
                VStack(alignment: .leading, spacing: 10) {
                    Text(pokemon.name)
                        .font(.headline)
                    Text("Type: \(pokemon.type)")
                    Text("Level: \(pokemon.level)")
                }
            }
            .navigationBarTitle("My Pokemon")
            .navigationBarItems(trailing: NavigationLink(destination: AddPokemonView()) {
                Image(systemName: "plus")
            })
        }
    }
}

struct PokemonListView_Previews: PreviewProvider {
    static var previews: some View {
        PokemonListView()
    }
}

AddPokemonView.swift (ポケモン追加画面)

import SwiftUI

struct AddPokemonView: View {
    @EnvironmentObject var pokemonStore: PokemonStore
    @State private var name = ""
    @State private var type = ""
    @State private var level = 1
    @Environment(\.presentationMode) var presentationMode

    var body: some View {
        Form {
            Section(header: Text("Name")) {
                TextField("Enter Pokemon name", text: $name)
            }
            Section(header: Text("Type")) {
                TextField("Enter Pokemon type", text: $type)
            }
            Section(header: Text("Level")) {
                Stepper(value: $level, in: 1...100) {
                    Text("\(level)")
                }
            }
            Button(action: addPokemon) {
                Text("Add Pokemon")
            }
        }
        .navigationBarTitle("Add Pokemon")
    }

    // ポケモン情報を追加する
    private func addPokemon() {
        if name.isEmpty || type.isEmpty {
            return
        }
        let pokemon = Pokemon(id: pokemonStore.pokemons.count + 1, name: name, type: type, level: level)
        pokemonStore.pokemons.append(pokemon)
        name = ""
        type = ""
        level = 1
        presentationMode.wrappedValue.dismiss()
    }
}

struct AddPokemonView_Previews: PreviewProvider {
    static var previews: some View {
        AddPokemonView()
    }
}