I am trying to create an auto-updating TableView, which is usually easy to do with help of Results.observe
(the replacement of .addNotificationBlock)
The problem I'm facing is that I can't figure out how to handle a tableView with multiple sections, and cells that can move from 1 section to another.
With below table as example: (as seen on UITableView with Multiple Sections using Realm and Swift)
Bulldogs
Charlie
Max
German Shepherd
Bella
Buddy
Molly
Golden Retrievers
Bailey
Siberian Huskies
Daisy
With
class Dog: Object {
@objc dynamic var name String?
@objc dynamic var race: String?
}
And then something along the lines of:
let results = realm.objects(Dog.self)
let token = dogs.observe { changes in
switch changes {
case .initial(let dogs):
break
case .update:
// HANDLE MOVING CELL TO DIFFERENT SECTION HERE
break
case .error:
break
}
}
Lets' say I have the tableView above, but 'Molly' had an identity crisis and turns out to be a Golden Retriever, so we change the race from within a detail screen.
How would I go about handling this change in an Observe block?
I have tried using 1 resultsList / token which triggers a modification when we change the race-property. But apart from a full reloadData(), which I can't use because I need animations, I can't figure out how to handle a delete & insert in 2 different sections because we can't reach the previous data in the 'dog'-object. Therefore I don't know how to figure out if a cell should move to a different section and what the previous section was.
I also tried using a resultsList per section, but this causes inconsistencies. When I change the race
property it triggers a modification (the dog object was changed), a deletion (the resultList.count for the previous section is -1) and an insert (the resultList.count for the new section = +1). These notifications don't trigger at the exact same time which causes the error:
'attempt to delete item x from section x, but there are only x sections before the update'
Has anyone figured out how to handle this gracefully? I actually need something similar to this in multiple tableView in the project i'm working on for an internship.
Thanks in advance
(First post, so please don't hesitate to correct me when this post is not up to standards)
------ EDIT WITH MORE SPECIFIC EXAMPLE CODE -----
The data class i'm using with some non-important properties removed
class CountInfo: Object, Encodable {
@objc dynamic var uuid: String?
@objc dynamic var productName: String?
// TableView is split in 2 sections based on this boolean-value
@objc dynamic var inStock: Bool = false
}
The code-stub in viewDidLoad() I would like to use to update my tableView with 2 sections
self.countListProducts = realm.objects(CountInfo.self)
self.token = self.countListProducts.observe {
changes in
AppDelegate.log.debug(changes)
if let tableView = self.tableView {
switch changes {
case .initial:
// if countInfo.isCounted = true: insert in section 0, if false: insert in section 1
// Currently handled by cellForRowAt
tableView.reloadData()
case .update(_, let deletions, let insertions, let modifications):
// Remove deletion rows from correct section
// Insert insertions into correct section
// Reload Cell if modification didn't change 'isCounted' property
// Remove from old section and insert in new section if 'isCounted' property changed
tableView.beginUpdates()
tableView.insertRows(at: insertions.map({ /* GET ROW TO INSERT */ }),
with: .automatic)
tableView.deleteRows(at: deletions.map({ /* GET ROW TO DELETE */ }),
with: .automatic)
tableView.reloadRows(at: modifications.map({ /* UPDATE NAME OR MOVE TO OTHER SECTION IF 'inStock' value Changed */ }),
with: .automatic)
tableView.endUpdates()
case .error(let error):
// An error occurred while opening the Realm file on the background worker thread
fatalError("\(error)")
}
}