Shob-Z Shob-Z - 5 months ago 107
iOS Question

How to use 'map' to map realm collection change notifications to UITableview sections?

Realm Collection Notifications works fine while mapping with UITableView rows using 'map'. How do i achieve the same by mapping it to UITableView sections.

For rows I follow the below code:

notificationToken = results.addNotificationBlock { [weak self] (changes: RealmCollectionChange) in
guard let tableView = self?.tableView else { return }
switch changes {
case .Initial:
tableView.reloadData()
break
case .Update(_, let deletions, let insertions, let modifications):
tableView.beginUpdates()
tableView.insertRowsAtIndexPaths(insertions.map { NSIndexPath(forRow: $0, inSection: 0) },
withRowAnimation: .Automatic)
tableView.deleteRowsAtIndexPaths(deletions.map { NSIndexPath(forRow: $0, inSection: 0) },
withRowAnimation: .Automatic)
tableView.reloadRowsAtIndexPaths(modifications.map { NSIndexPath(forRow: $0, inSection: 0) },
withRowAnimation: .Automatic)
tableView.endUpdates()
break
case .Error(let error):
// An error occurred while opening the Realm file on the background worker thread
fatalError("\(error)")
break
}
}


For sections, I work with:

tableview.beginUpdates()
for insertIndex in insertions {
tableview.insertSections(NSIndexSet(index: insertIndex), withRowAnimation: .Automatic)
}
for deleteIndex in deletions {
tableview.deleteSections(NSIndexSet(index: deleteIndex), withRowAnimation: .Automatic)
}
for reloadIndex in modifications {
tableview.reloadSections(NSIndexSet(index: reloadIndex), withRowAnimation: .Automatic)
}
tableview.endUpdates()


And this works.

But I want to know about 'map' and how to use it to map sections.

tableView.insertSections(insertions.map { NSIndexSet(index: $0) }, withRowAnimation: .Automatic)


And also,

tableview.insertSections(insertions.map({ (index) -> NSIndexSet in
NSIndexSet(index: index)
}), withRowAnimation: .Automatic)


But, both gives me the same error


'map' produces '[T]', not the expected contextual result type 'NSIndexSet'

Answer

map returns a new collection by replacing each of the original collection elements with a mapped version of that same element. In other words:

insertions.map { ...}

returns an array, while tableView.insertSections expects a single NSIndexSet argument.

The closest you're going to get is:

for indexSet in insertions.map { NSIndexSet(index: $0) } {
    tableView.insertSections(indexSet, ...)
}

Alternatively, you can create a NSIndexSet that's a conjunction of the individual elements using reduce, something like:

tableView.insertSections(insertions.reduce(NSMutableIndexSet()) {
    $0.addIndex($1)
    return $0
}, withRowAnimation: .Automatic)

But that really seems to be obscuring the code rather than clarifying it.