必要最小限のアプリでRealmSwiftを試してみる
今日は、RealmSwiftを初めて使ってみます。
まずは動かしてみたいので、必要最小限の「ToDoアプリ」にRealmSwiftを追加して、変更内容が保存されたら成功とします。
ToDoアプリ(RealmSwift追加前)
import SwiftUI
struct RoundedButtonStyle: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.padding(EdgeInsets(
top: 7, leading: 10, bottom: 7, trailing: 10
))
.foregroundColor(.white)
.background(.blue)
.cornerRadius(7)
.opacity(configuration.isPressed ? 0.5 : 1)
}
}
struct ContentView: View {
@State var inputTitle: String = ""
@State var toDoList = ["猫に餌をやる", "雨戸を開ける", "洗濯をする"]
var body: some View {
VStack {
TextField("やることを入力", text: $inputTitle)
.textFieldStyle(.roundedBorder)
.padding(EdgeInsets(
top: 10, leading: 10, bottom: 5, trailing: 10
))
Button(action: {
if !inputTitle.isEmpty {
toDoList.append(inputTitle)
inputTitle = ""
}
}, label: {
Text("追加")
})
.buttonStyle(RoundedButtonStyle())
List {
ForEach(toDoList, id: \.self) { toDo in
Text(toDo)
} // ForEach
.onDelete(perform: deleteTitles)
} // List
} // VStack
} // body
func deleteTitles(at offsets: IndexSet) {
toDoList.remove(atOffsets: offsets)
}
} // ContentView
配列をListで表示して、やることの追加と削除だけできるようにした、シンプルなアプリです。

ここにRealmSwiftを追加して、ToDoリストの内容を変更した後にアプリを落としても、変更内容が保存されているようにしていきます。
テーブル定義クラスを追加
import Foundation
import RealmSwift
class ToDo: Object, ObjectKeyIdentifiable {
@Persisted(primaryKey: true) var id: UUID = UUID()
@Persisted var title: String = ""
}
ToDo.swiftを作成して、データベースのテーブル定義を設定したクラス作ります。
カラムに当たるプロパティには、@Persistedを付与します。
ViewModelクラスを追加
import Foundation
import RealmSwift
// ViewModel
class ToDoViewModel: ObservableObject {
private var realm: Realm
@Published var toDoList: [ToDo] = []
init() {
do {
realm = try Realm()
loadToDos()
} catch {
print("Failed to open Realm. Error: \(error.localizedDescription)")
realm = try! Realm(configuration: .init(inMemoryIdentifier: "TemporaryRealm"))
}
}
func loadToDos() {
let todos = realm.objects(ToDo.self)
toDoList = Array(todos)
}
func addToDo(title: String) {
let newToDo = ToDo()
newToDo.title = title
do {
try realm.write {
realm.add(newToDo)
}
loadToDos()
} catch {
print("Failed to add ToDo. Error: \(error.localizedDescription)")
}
}
func deleteToDos(at offsets: IndexSet) {
offsets.map { toDoList[$0] }.forEach { toDo in
do {
try realm.write {
realm.delete(toDo)
}
} catch {
print("Failed to delete ToDo. Error: \(error.localizedDescription)")
}
}
loadToDos()
}
}
Realmデータベースを使用して、アプリケーションのToDoリストの管理を行うためのToDoViewModelクラスを作成します。
ContentViewを変更
import SwiftUI
struct RoundedButtonStyle: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.padding(EdgeInsets(
top: 7, leading: 10, bottom: 7, trailing: 10
))
.foregroundColor(.white)
.background(.blue)
.cornerRadius(7)
.opacity(configuration.isPressed ? 0.5 : 1)
}
}
struct ContentView: View {
@State var inputTitle: String = ""
- @State var toDoList = ["猫に餌をやる", "雨戸を開ける", "洗濯をする"]
+ @StateObject private var viewModel = ToDoViewModel()
var body: some View {
VStack {
TextField("やることを入力", text: $inputTitle)
.textFieldStyle(.roundedBorder)
.padding(EdgeInsets(
top: 10, leading: 10, bottom: 5, trailing: 10
))
Button(action: {
if !inputTitle.isEmpty {
- toDoList.append(inputTitle)
+ viewModel.addToDo(title: inputTitle)
inputTitle = ""
}
}, label: {
Text("追加")
})
.buttonStyle(RoundedButtonStyle())
- List {
- ForEach(toDoList, id: \.self) { toDo in
- Text(toDo)
- } // ForEach
- .onDelete(perform: deleteTitles)
- } // List
+ List {
+ ForEach(viewModel.toDoList) { toDo in
+ Text(toDo.title)
+ } // ForEach
+ .onDelete(perform: viewModel.deleteToDos)
+ } // List
} // VStack
} // body
func deleteTitles(at offsets: IndexSet) {
toDoList.remove(atOffsets: offsets)
}
} // ContentView
最後に、ContentView.swiftの中でToDoViewModelクラスをインスタンス化して、ToDoViewModelに定義したメソッドでリストの追加・削除を行うように書き換えます。

アプリの起動中に追加・削除を行なったリストの内容が、アプリ停止後に再起動しても保存されています!
ご覧いただき、ありがとうございました。