I'm migrating all CoreData related code and models in my project to CoreStore right now, because it just seemed more convenient to me. But while replacing an NSFetchedResultsController with a sectioned list Monitor and ListSectionObserver I encountered the issue that the list does not get refreshed after an object is inserted, removed or dealt with in any other manner, because the functions of the Observer do not get called. That ultimately leads to the list being incomplete and wrong objects getting returned when clicking on a cell or - in the case of deletion - to a crash.
I would greatly appreciate any help, maybe I'm just forgetting something really obvious.
Originally created by @timfraedrich on GitHub (Oct 3, 2019).
CoreStore: 6.3.1
Swift: 5.1
Xcode: 11.0
Simulator: Xr iOS 13.0
I'm migrating all CoreData related code and models in my project to CoreStore right now, because it just seemed more convenient to me. But while replacing an NSFetchedResultsController with a sectioned list Monitor and ListSectionObserver I encountered the issue that the list does not get refreshed after an object is inserted, removed or dealt with in any other manner, because the functions of the Observer do not get called. That ultimately leads to the list being incomplete and wrong objects getting returned when clicking on a cell or - in the case of deletion - to a crash.
Here is the code I wrote:
```swift
struct DataManager {
static let monitor = CoreStore.monitorSectionedList(
From<MyCoreStoreObject>()
.sectionBy(\.dayIdentifier)
.orderBy(.descending(\.startDate))
)
}
class ViewController: UITableViewController, ListSectionObserver {
typealias ListEntityType = MyCoreStoreObject
override func viewDidLoad() {
DataManager.monitor.addObserver(self)
super.viewDidLoad()
}
deinit {
DataManager.monitor.removeObserver(self)
}
// MARK: TableView
override func numberOfSections(in tableView: UITableView) -> Int {
return DataManager.monitor.numberOfSections()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
guard let sectionCount = DataManager.monitor.numberOfObjects(safelyIn: section) else {
return 0
}
return sectionCount
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let object = DataManager.monitor.objects(in: indexPath.section)[indexPath.row]
let cell = ObjectCell(object: object)
return cell
}
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let dayIdentifier = DataManager.monitor.sectionIndexTitles()[section]
let header = ListHeader(dayIdentifier: dayIdentifier)
return header
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let workout = DataManager.monitor.objects(in: indexPath.section)[indexPath.row]
// display view controller
}
// MARK: ListObserver
func listMonitorWillChange(_ monitor: ListMonitor<MyCoreStoreObject>) {
self.tableView.beginUpdates()
}
func listMonitorDidChange(_ monitor: ListMonitor<MyCoreStoreObject>) {
self.tableView.endUpdates()
}
func listMonitorWillRefetch(_ monitor: ListMonitor<MyCoreStoreObject>) {
}
func listMonitorDidRefetch(_ monitor: ListMonitor<MyCoreStoreObject>) {
self.tableView.reloadData()
}
// MARK: ListObjectObserver
func listMonitor(_ monitor: ListMonitor<MyCoreStoreObject>, didInsertObject object: MyCoreStoreObject, toIndexPath indexPath: NSIndexPath) {
let indexPath = indexPath as IndexPath
self.tableView.insertRows(at: [indexPath], with: .fade)
}
func listMonitor(_ monitor: ListMonitor<MyCoreStoreObject>, didDeleteObject object: MyCoreStoreObject, fromIndexPath indexPath: NSIndexPath) {
let indexPath = indexPath as IndexPath
self.tableView.deleteRows(at: [indexPath], with: .fade)
}
func listMonitor(_ monitor: ListMonitor<MyCoreStoreObject>, didUpdateObject object: MyCoreStoreObject, atIndexPath indexPath: NSIndexPath) {
let indexPath = indexPath as IndexPath
if let cell = self.tableView.cellForRow(at: indexPath) as? ObjectCell {
cell.object = object
cell.setup()
}
}
func listMonitor(_ monitor: ListMonitor<MyCoreStoreObject>, didMoveObject object: MyCoreStoreObject, fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
let fromIndexPath = fromIndexPath as IndexPath
self.tableView.deleteRows(at: [fromIndexPath], with: .fade)
let toIndexPath = toIndexPath as IndexPath
self.tableView.insertRows(at: [toIndexPath], with: .fade)
}
// MARK: ListSectionObserver
func listMonitor(_ monitor: ListMonitor<MyCoreStoreObject>, didInsertSection sectionInfo: NSFetchedResultsSectionInfo, toSectionIndex sectionIndex: Int) {
self.tableView.insertSections(IndexSet(arrayLiteral: sectionIndex), with: .fade)
}
func listMonitor(_ monitor: ListMonitor<MyCoreStoreObject>, didDeleteSection sectionInfo: NSFetchedResultsSectionInfo, fromSectionIndex sectionIndex: Int) {
self.tableView.deleteSections(IndexSet(arrayLiteral: sectionIndex), with: .fade)
}
}
```
I would greatly appreciate any help, maybe I'm just forgetting something really obvious.
I did try to insert it in other ways though (with unsafe and synchronous transactions) and that did not do anything different. The object is also there after I restart the app. The Observer is just not notified of a change.
@timfraedrich commented on GitHub (Oct 3, 2019):
> Can you show some code from the transaction
Yes of course:
```swift
static func saveObject(..., completion: @escaping (Bool, Error?, MyCoreStoreObject?) -> Void) {
CoreStore.perform(asynchronous: { (transaction) -> MyCoreStoreObject in
let object = transaction.create(Into<MyCoreStoreObject>())
object. ...
for data in dataArray {
let dataObject = transaction.create(Into<DataObject>())
dataObject. ...
dataObject.object .= object
}
return object
}) { (result) in
switch result {
case .success(let object):
completion(true, nil, object)
case .failure(let error):
completion(false, error, nil)
}
}
}
```
I did try to insert it in other ways though (with unsafe and synchronous transactions) and that did not do anything different. The object is also there after I restart the app. The Observer is just not notified of a change.
Okay I found the solution: It turns out one should not blindly copy code from the documentation. It seems that it is not accurate anymore, since the NSIndexPath changed to IndexPath. The Observer now gets called with no issues.
@timfraedrich commented on GitHub (Oct 4, 2019):
Okay I found the solution: It turns out one should not blindly copy code from the documentation. It seems that it is not accurate anymore, since the NSIndexPath changed to IndexPath. The Observer now gets called with no issues.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Originally created by @timfraedrich on GitHub (Oct 3, 2019).
CoreStore: 6.3.1
Swift: 5.1
Xcode: 11.0
Simulator: Xr iOS 13.0
I'm migrating all CoreData related code and models in my project to CoreStore right now, because it just seemed more convenient to me. But while replacing an NSFetchedResultsController with a sectioned list Monitor and ListSectionObserver I encountered the issue that the list does not get refreshed after an object is inserted, removed or dealt with in any other manner, because the functions of the Observer do not get called. That ultimately leads to the list being incomplete and wrong objects getting returned when clicking on a cell or - in the case of deletion - to a crash.
Here is the code I wrote:
I would greatly appreciate any help, maybe I'm just forgetting something really obvious.
@JohnEstropia commented on GitHub (Oct 3, 2019):
How does your transaction insert those objects? Can you show some code from the transactions side?
@timfraedrich commented on GitHub (Oct 3, 2019):
Yes of course:
I did try to insert it in other ways though (with unsafe and synchronous transactions) and that did not do anything different. The object is also there after I restart the app. The Observer is just not notified of a change.
@timfraedrich commented on GitHub (Oct 4, 2019):
Okay I found the solution: It turns out one should not blindly copy code from the documentation. It seems that it is not accurate anymore, since the NSIndexPath changed to IndexPath. The Observer now gets called with no issues.