今回はメインビューとなるContentView.swiftから、サブビュー(TaskEditView.swift)へ、CoreDataで取得したデータを渡す方法を紹介する。
ここで使用するサンプルアプリは以下の記事で紹介している。
サブビューを用意する
まず、サブビューとしてTaskEditView.swiftを作成する。
import SwiftUI
import CoreData
struct TaskEditView: View {
@ObservedObject var task: Task
var body: some View {
VStack {
Text(task.name)
}.padding()
.navigationBarTitle("編集画面")
}
}
CoreDataのエンティティを受け取る場合に必要なのが、5行目の宣言。
@ObservedObjectを付けることで、インスタンスがSwiftUIの監視対象となり、プロパティが更新されると参照されているViewも自動的に更新されるようになる。
NavigationLinkでサブビューにエンティティを渡す
次にメインビューとなるContentView.swiftを以下のとおり編集する。
コード全文
import SwiftUI
import CoreData
struct ContentView: View {
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \Task.date, ascending: false)],
animation: .default
)
var tasks: FetchedResults<Task>
@Environment(\.managedObjectContext) var viewContext
@State var new = ""
var body: some View {
NavigationView {
VStack {
HStack {
TextField("Input here", text: $new)
.textFieldStyle(RoundedBorderTextFieldStyle())
Button(action: {
let newTask = Task(context: self.viewContext)
newTask.name = self.new
newTask.date = Date()
self.saveCoreData()
self.new = ""
}) {
Text("追加")
}
}
List {
ForEach(tasks.indices, id: \.self) { index in
NavigationLink(destination: TaskEditView(task: self.tasks[index])) {
Text("\(self.tasks[index].name)")
}
}.onDelete(perform: removeTask)
}
}.padding()
.navigationBarTitle("タスク一覧")
}
}
private func removeTask(at offsets: IndexSet) {
for index in offsets {
let putTask = tasks[index]
viewContext.delete(putTask)
}
saveCoreData()
}
private func saveCoreData() {
do {
try self.viewContext.save()
} catch {
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
}
}
少し長いコードだが、エンティティの受け渡しはこちらの部分。
List {
ForEach(tasks.indices, id: \.self) { index in
NavigationLink(destination: TaskEditView(task: self.tasks[index])) {
Text("\(self.tasks[index].name)")
}
}.onDelete(perform: removeTask)
}
NavigationLinkを使って、遷移先のビューにエンティティを渡している。
アプリを実行し、テスト用にいくつかのタスクを登録した画面がこちら。
タスク名をタップするとサブビューに遷移し、選択したタスク名が表示される。