Reputation: 10738
The following code works fine for adding new ItemList
s and adding new Items
s to the ItemList
s. What I'm having issues with is deleting all items from a list. In other words I have a button (deleteAllItems
) which is supposed to delete all items from the selected list, but the way I have it right now it deletes ALL Item
s in Realm
regardless of what list owns them.
What is the right way to create multiple ItemList
s which would contain multiple Item
s and have the ability to delete all Item
s from a certain list?
class ItemList: Object {
dynamic var listName = ""
dynamic var createdAt = NSDate()
let items = List<Item>()
}
class Item: Object {
dynamic var productName = ""
dynamic var createdAt = NSDate()
}
class ViewController: UIViewController, UITableViewDataSource{
@IBOutlet weak var tableListOfItems: UITableView!
@IBOutlet weak var inputProductName: UITextField!
@IBOutlet weak var inputListName: UITextField!
var allItems : Results<Item>!
override func viewDidLoad() {
super.viewDidLoad()
updateData()
}
@IBAction func addNewList(_ sender: Any) {
let list = ItemList()
list.listName = inputListName.text!
try! realm.write {
realm.add(list)
}
}
@IBAction func addNewItem(_ sender: Any) {
let newItem = Item()
newItem.productName = inputProductName.text!
let list = realm.objects(ItemList.self).filter("listName = 'List Name Here'").first!
try! realm.write {
list.items.append(newItem)
updateData()
}
}
func updateData(){
allItems = realm.objects(Item.self)
tableListOfItems.reloadData()
}
/// This deletes every Item in Realm which is not what
/// I want. I want to delete only items that belong to
/// a certain list. I tried...
/// let list = realm.objects(ItemList.self).filter("listName = 'Default List'").first!
/// list.items.removeAll()
@IBAction func deleteAllItems(_ sender: Any) {
try! realm.write {
realm.delete(realm.objects(Item.self))
updateData()
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return allItems.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "myCell", for: indexPath)
let data = allItems[indexPath.row]
cell.textLabel?.text = data.productName
return cell
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == UITableViewCellEditingStyle.delete{
if let item = allItems?[indexPath.row] {
try! realm.write {
realm.delete(item)
}
tableView.deleteRows(at: [indexPath], with: UITableViewRowAnimation.automatic)
}
}
}
}
Upvotes: 1
Views: 1289
Reputation: 54716
In your deleteAllItems function you should filter them. Without filtering this is the expected behaviour, since you only specify an object class, so Realm will obviously delete all objects matching that class.
If you want to delete all items from Realm itself that are contained in the List, but keep the empty list, you need to change your deleteAllItems function the following way:
@IBAction func deleteAllItems(_ sender: Any) {
guard let listToDelete = realm.objects(ItemList.self).filter("listName = %@",listNameToDelete).first else { return }
try! realm.write {
for item in listToDelete.items {
realm.delete(realm.objects(Item.self).filter("productName = %@", item.productName).first)
updateData()
}
}
}
listNameToDelete should be declared either outside your function in your class or you can declare it inside the function as well depending on what you actually want to achieve with this. Also, this implementation assumes that your listNames and productNames are unique.
Upvotes: 2