我使用Relam在本地存储数据,工作正常,但当我尝试添加带有导航链接的新记录时,它也会返回重复记录。另一个问题是,当我单击记录时,我希望更改导航,但由于它有重复的记录,第一个记录不起作用,但第二个记录起作用。
这是模型。
import SwiftUI
import RealmSwift
struct Task: Identifiable {
var id: String
var title: String
var completed: Bool = false
var completedAt: Date = Date()
init(taskObject: TaskObject) {
self.id = taskObject.id.stringValue
self.title = taskObject.title
self.completed = taskObject.completed
self.completedAt = taskObject.completedAt
}
}
这是持久模型。。。
import Foundation
import RealmSwift
class TaskObject: Object {
@Persisted(primaryKey: true) var id: ObjectId
@Persisted var title: String
@Persisted var completed: Bool = false
@Persisted var completedAt: Date = Date()
}
这是视图模型。。
/
/ 2
final class TaskViewModel: ObservableObject {
// 3
@Published var tasks: [Task] = []
// 4
private var token: NotificationToken?
init() {
setupObserver()
}
deinit {
token?.invalidate()
}
// 5
private func setupObserver() {
do {
let realm = try Realm()
let results = realm.objects(TaskObject.self)
token = results.observe({ [weak self] changes in
// 6
self?.tasks = results.map(Task.init)
.sorted(by: { $0.completedAt > $1.completedAt })
.sorted(by: { !$0.completed && $1.completed })
})
} catch let error {
print(error.localizedDescription)
}
}
// 7
func addTask(title: String) {
let taskObject = TaskObject(value: [
"title": title,
"completed": false
])
do {
let realm = try Realm()
try realm.write {
realm.add(taskObject)
}
} catch let error {
print(error.localizedDescription)
}
}
// 8
func markComplete(id: String, completed: Bool) {
do {
let realm = try Realm()
let objectId = try ObjectId(string: id)
let task = realm.object(ofType: TaskObject.self, forPrimaryKey: objectId)
try realm.write {
task?.completed = completed
task?.completedAt = Date()
}
} catch let error {
print(error.localizedDescription)
}
}
func remove(id: String) {
do {
let realm = try Realm()
let objectId = try ObjectId(string: id)
if let task = realm.object(ofType: TaskObject.self, forPrimaryKey: objectId) {
try realm.write {
realm.delete(task)
}
}
} catch let error {
print(error.localizedDescription)
}
}
func updateTitle(id: String, newTitle: String) {
do {
let realm = try Realm()
let objectId = try ObjectId(string: id)
let task = realm.object(ofType: TaskObject.self, forPrimaryKey: objectId)
try realm.write {
task?.title = newTitle
}
} catch let error {
print(error.localizedDescription)
}
}
}
这是主视图。。
@main
struct RelamDemoSwiftUIApp: App {
var body: some Scene {
WindowGroup {
ContentView().environmentObject(TaskViewModel())
}
}
}
这是内容视图的代码。。
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
VStack {
AddTaskView()
TaskListView()
}
.navigationTitle("Todo")
.navigationBarTitleDisplayMode(.automatic)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
以下是添加任务视图的代码。。
import SwiftUI
struct AddTaskView: View {
@State private var taskTitle: String = ""
@EnvironmentObject private var viewModel: TaskViewModel
var body: some View {
HStack(spacing: 12) {
TextField("Enter New Task..", text: $taskTitle)
Button(action: handleSubmit) {
Image(systemName: "plus")
}
}
.padding(20)
}
private func handleSubmit() {
viewModel.addTask(title: taskTitle)
taskTitle = ""
}
}
这是任务列表视图。。
struct TaskListView: View {
@EnvironmentObject private var viewModel: TaskViewModel
var body: some View {
ScrollView {
LazyVStack (alignment: .leading) {
ForEach(viewModel.tasks, id: \.id) { task in
TaskRowView(task: task)
Divider().padding(.leading, 20)
NavigationLink (destination: TaskView(task: task)) {
TaskRowView(task: task)
}.animation(.default)
}
}
}
}
}
这是任务代码。。
struct TaskView: View {
// 1
@EnvironmentObject private var viewModel: TaskViewModel
// 2
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
@State private var taskTitle: String = ""
// 3
let task: Task
var body: some View {
VStack(alignment: .leading, spacing: 24) {
// 4
VStack(alignment: .leading, spacing: 4) {
Text("Title")
.foregroundColor(Color.gray)
TextField("Enter title..", text: $taskTitle)
.font(.largeTitle)
Divider()
}
// 5
Button(action: deleteAction) {
HStack {
Image(systemName: "trash.fill")
Text("Delete")
}
.foregroundColor(Color.red)
}
Spacer()
}
.navigationBarTitle("Edit Todo", displayMode: .inline)
.padding(24)
.onAppear(perform: {
taskTitle = task.title
})
// 6
.onDisappear(perform: updateTask)
}
private func updateTask() {
viewModel.updateTitle(id: task.id, newTitle: taskTitle)
}
private func deleteAction() {
viewModel.remove(id: task.id)
presentationMode.wrappedValue.dismiss()
}
}
这是截图