我使用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() } }
这是截图