mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-01-11 20:00:30 +01:00
ListMonitor doesn't return initial dataset if created right after addPersistentStoreAndWait() #38
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @jamesbebbington on GitHub (Feb 8, 2016).
Having implemented a sectioned
ListMonitoras the datasource for my controller, I'm finding that it only returns records when the underlying store content changes.I boot my app, insert data into the store and the table view is updated accordingly. But when I restart the app, the table view is empty. However, a
CoreStore.fetchAllreveals that there is data in the store.Am I doing anything obviously wrong?
Incidentally, the ListObserver demos in the CoreStoreDemo app initially appear empty too, which was unexpected (are they meant to start empty?) and led me to wonder if CoreStore might be at fault:
Thanks.
@JohnEstropia commented on GitHub (Feb 9, 2016):
I can't find anything wrong in your code, architectually sound actually, but you can try check the following:
tableView.reloadData()at the end of viewDidLoad or viewWillAppearWhere(true)clauseThe demo app starts with a clean database, but after you add some items and try to restart the app, the previous entries should be visible.
@jamesbebbington commented on GitHub (Feb 9, 2016):
Thanks, it's my first Cocoa app so that's good to hear.
It's not an
IBOutletbut adding it as one and callingreloadData()doesn't help.Ah yes, I did try this, and should have mentioned it in my previous post. Adding breakpoints to the
UITableViewDataSourcemethods reveals thatnumberOfSectionsInTableViewis called six times, and each timeprojects.numberOfSections()returns0, where I would expect it to return2for my dataset (as it does after an initial data fetch):This led me to suspect the sectioned list monitor might be playing up, but converting it to a plain list monitor makes no difference:
Ah thanks, I wasn't sure about that.
OK, thanks for the clarification, it wasn't obvious to me from the source what the expected behaviour was.
Ah ha! I definitely I tried adding this in various places before and it had no effect, but a
projects.refetch()at the end ofviewDidLoad()seems to do the trick.Can we conclude that there is something not quite right with
ListMonitor, as I presume that this shouldn't be necessary?@JohnEstropia commented on GitHub (Feb 9, 2016):
Thanks for sharing your debugging info! Getting it fixed by calling
refetch()(it definitely shouldn't be needed) makes me think that your ListMonitor is getting initialized before the NSPersistentStore gets added completely to the stack.addSQLiteStore...()is setup and when it gets called?My guess is either:
addSQLiteStore(...)and the view controller is created before the completion is called. Or,addSQLiteStoreAndWait(...)one but the view controller is created right after it on the same run loop. (if so, this could be be a bug in CoreStore or an undocumented behavior of NSPersistentStoreCoordinator)@jamesbebbington commented on GitHub (Feb 9, 2016):
You're welcome, hopefully it'll help others who might have similar issues too.
Ah, yeah that sounds like a possibility.
I'm calling
CoreStore.addSQLiteStoreAndWait()inapplicationDidFinishLaunching(application: UIApplication).Yes, indirectly. The
ProjectsControlleris a child of myRootControllerwhich is the initial controller.Yeah, it looks like the latter is the problem. If I remove the
refetch()workaround and change theListMonitorproperty from a constant to a lazy var the problem goes away:@JohnEstropia commented on GitHub (Feb 9, 2016):
Okay, I'll try to see if there's a way to handle this from within CoreStore. I'm not sure how to proceed so far though, as I already use
NSPersistentStoreCoordinator.performBlockAndWait { ... }.Anyway I'm glad using
lazyfixed it for you. You can also skip the closure altogether and just declare it this way:@jamesbebbington commented on GitHub (Feb 9, 2016):
Sounds like a tricky one. Maybe there's some inspiration to be found in the source of
Signalsand itslistenPastfunctionality.Ah yes, cheers and thanks for all your help on this one!
@JohnEstropia commented on GitHub (Feb 10, 2016):
@fractious
Yup, if I find a notification to listen for it might be easy to implement on
addSQLiteStore(..., completion:)(async version). My concern is if it is possible at all for the synchronousaddSQLiteStoreAndWait(...)method.I'll try to see if there's a workaround. Thanks for the detailed investigation!
@JohnEstropia commented on GitHub (Feb 11, 2016):
@fractious Can I ask one more thing? What iOS version are you having this problem?
I can't seem to reproduce this with the demo app on iOS 9 (even if I set the Colors Demo as the initial view controller)
@JohnEstropia commented on GitHub (Feb 11, 2016):
The only way I have reproduced this is to call
addSQLiteStoreAndWait()right aftermonitorSectionedList()... Can you check again with breakpoints which gets called first in your previous setup? (without thelazyfix)@jamesbebbington commented on GitHub (Feb 11, 2016):
I've been using iOS 9.2 in the iPhone 5s simulator.
Yeah that what appears to be happening, my
ProjectsControlleris instantiated beforeapplicationDidFinishLaunching()is called.An alternative fix to lazily instantiating the
ListMonitoris to move theaddSQLiteStoreAndWait()to a property declaration, so that it fires first:Obviously the above example will cause the app to crash if the method
throws, but it could always be changed to a computed property thatcatches.Is the above something you'd recommend over the
lazyalternative?@JohnEstropia commented on GitHub (Feb 11, 2016):
@fractious I see, so it's not a problem with Core Data after all. I'll add an
assert()on ListMonitor to prevent getting created without any persistent stores.As for your app, you can adopt the style that the demo app uses:
I'll close this issue as it seems to be fixable on the client side. I already added the
asserton my local repository so it should be in the develop branch soon. Thanks again for the prompt responses! If there's anything else feel free to message anytime :)@jamesbebbington commented on GitHub (Feb 11, 2016):
Cheers @JohnEstropia and thanks for helping get to the bottom of this one, much appreciated.
I think I'll keep my
CoreStore.addSQLiteStoreAndWait()in theAppDelegateas I've got a number ofListSectionObservercontrollers so would like to keep them DRY. I'll run with non-lazyfix for now and see how that goes.