使用Realm数据库向Table View添加条目时出现重复存储问题
Hey there! The root cause of your duplicate entries is that you're reusing the same RealmEventItem instance every time you add a new event. Let's break down what's happening and fix it step by step.
The Problem with Your Current Code
Right now, every time you tap "Add", you're modifying the existing self.realmEventItem (which is already saved in Realm) and then trying to insert it again with realm.create(...). Since this object is already managed by Realm, this doesn't create a new entry—it either throws an error (hidden by your try!) or causes unexpected behavior like overwriting existing entries and duplicating them on app restart.
The Fix: Create a New Instance for Each Event
You need to initialize a brand new RealmEventItem every time you add a new event. Here's the revised code for your "Add" action:
newEventAlert.addAction(PMAlertAction(title: "Add", style: .default, action: { print("Add Event Button Pressed in Alert") // First, validate all required inputs guard let eventName = self.nameOfEvent.text, !eventName.isEmpty, let dayText = self.dayOfEvent.text, !dayText.isEmpty, let monthText = self.monthOfEvent.text, !monthText.isEmpty else { print("Missing Information!") return } // Create a NEW RealmEventItem instance for the new event let newEvent = RealmEventItem() newEvent.nameOfEventRealm = eventName newEvent.dateOfEventRealm = "\(dayText) \(monthText)" newEvent.oneDayBeforeReminderRealm = self.oneDayReminder.text == "Yes" newEvent.sevenDaysBeforeReminderRealm = self.sevenDayReminder.text == "Yes" // Save the new event to Realm do { try realm.write { realm.add(newEvent) // Use add() for new unmanaged objects } } catch { print("Failed to save event: \(error.localizedDescription)") return } // Update the table view to show the new entry let newIndexPath = IndexPath(row: self.realmEventList.count - 1, section: 0) self.tableView.insertRows(at: [newIndexPath], with: .automatic) self.labelWhenTableViewIsEmpty.text = "" print("Added to Table View | Total events: \(self.realmEventList.count)") // Reset inputs and pickers self.nameOfEvent.text = "" self.dayPickerView.selectRow(0, inComponent: 0, animated: false) self.monthPickerView.selectRow(0, inComponent: 0, animated: false) self.oneDayPickerView.selectRow(0, inComponent: 0, animated: false) self.sevenDayPickerView.selectRow(0, inComponent: 0, animated: false) print("All Realm events: \(realm.objects(RealmEventItem.self))") }))
Key Changes Explained
- New Instance per Event: We create
newEventas a freshRealmEventIteminstead of reusingself.realmEventItem. This ensures we're adding a completely new entry to Realm. - Input Validation First: We moved the input check to the top using
guard—this exits early if any required field is empty, making the code cleaner and more efficient. - Safe Error Handling: Replaced
try!withdo-catchto handle Realm write errors gracefully, avoiding silent crashes that are hard to debug. - Correct Realm Method: Used
realm.add(newEvent)instead ofcreate—add()is designed for inserting new unmanaged objects, whilecreate()is meant for updating existing objects (when using a primary key) or creating unique entries.
Extra Tips to Avoid Future Issues
- Define a Primary Key (If Needed): If you want to prevent duplicate events with the same name, add a primary key to your
RealmEventItemmodel:
Then you can useclass RealmEventItem: Object { @Persisted(primaryKey: true) var nameOfEventRealm: String // ... other properties ... }realm.create(RealmEventItem.self, value: newEvent, update: .all)to either create a new event or update an existing one with the same name. - Avoid Reusing Managed Objects: Never modify a managed Realm object (one that's already saved) unless you intend to update the existing entry in the database.
内容的提问来源于stack exchange,提问作者LearningCoding18

