NSAsychronousFetchResult after the app is DidEnterBackground - ios

I have a client app with coredata as its back end. Its simple enough, with two entities.
UPDATE: Using CloudKit as the sync service. I'm not really sure what is going on there. Except I can query and get results, incase things don't automatically work. The problem is, as I noticed with most third-party sync-service providers. 95% of the time, they all work. Its when I test it with a more than a few devices / simultaneous calls that some undesired change comes in.
This question is more about iOS and coredata than the actual syncing architecture.
there are times when there is definite sync data loss. I really can't tell when and how. That im still figuring out. Sometimes initial sync takes a long time (if theres existing data) and the user might close the app, (some people double press the home button and actually close apps!).
But no matter what I do, sometimes i miss an object, sometimes an attribute.
So I saw this NSAsynchronousFetchRequest and I thought about giving me an option to check if all local-data (coredata) is okay, to see if theres anything missing.
Perhaps i could use a simple predicate to see of some managedObject.title == nil and fetch its identifier. Collect those faulty objects and request the truth server for data for these objects? Is this a good use of NSAsynchronousFetchRequest?
If yes, when during the lifetime of the app would this be good?
Im thinking maybe after applicationDidEnterBackround would be a good time..? Then If I do get it, will need a good way to manage CoreData in the background!
If no, well.. Really don't know wat to do then.
Im trying to actually do this, will update with my results.
UPDATE: Question updated to reflect the use of Cloudkit

Related

Delay in CoreData to PersistentCoudKitContainer synchronization

I am having an issue with my CoreData to iCloud synchronization with NSPersistentCloudKitContainer.
The synchronization works, but when i do a fresh install of the app there is an annoying delay of several seconds between app launch and the end of synchronization. I need to decide at launch whether to create new data entities or use the "old" data from iCloud.
I could live with the delay and wait for the sync to finish if there was a way to
a) determine at launch that there is data in iCloud to be synchronized and
b) get a notification when synchronization is finally done
Does anyone know of a solution to achieve this? Setting
NSPersistentStoreRemoteChangeNotificationPostOptionKey does not help much, as it is fired several times during sync and does not give any status information.
At the risk of providing you the most unhelpful answer possible, I don't think it is possible and, even if it is, I think you are battling against the philosophy of NSPersistentCloudKitContainer.
With NSPersistentCloudKitContainer, you should assume that synchronisation happens at irregular, erratic intervals or not at all. It is supposed to operate seamlessly, in the background, with nothing for you to worry about. You shouldn't try to speculate in your code when it happens or if it happens.
It is very similar to taking a photo on your iPhone and then it taking several seconds for that photo to appear on your iMac. The iCloud sync decides if and when that sync will take place.
I know this is not helpful, but I thought you should be aware of this perspective.

When to update my persistent storage (core data)?

I have a NSObject that I manipulate quite a lot, as the user changes different things. It seems a bit crazy to update the core data every single time there is a change. It would require a lot of coding just for one little change in these different places.
When should I update the core data if I want my stuff to persist? Is it a bad idea to only update it before the app closes?
Thanks
When should I update the core data if I want my stuff to persist?
Basically, you save whenever you feel that the changes are significant enough and should be saved.
Is it a bad idea to only update it before the app closes?
If the changes are important and you don't want them to get lost, what do you think happens in case the app crashes or terminates, battery dies etc..? Well, all the changes get lost if you havn't saved it.
It seems a bit crazy to update the core data every single time there
is a change.
Well, the application can not magically know what is important to you that should be saved and what would not. This is how it works generally for everything.
So basically, thats the guideline, the rest is up to you.

Firebase iOS - Snapshot isn't updated but database is?

I've been having this issue at random times for quite a while, where I will physically be looking at my firebase console and see that I have deleted a piece of data, and then in code I will call print(snapshot.ref) and see the correct reference (copy and pasted in browser to double check too), yet somehow when I try to get the values of the snapshot/iterate over its children the snapshot is containing old data that is not in the database anymore.
let key2 = ref.child(users).child("Employees").observeSingleEvent(of: FIRDataEventType.value, with: { (snapshot) in
print(snapshot)
for child in snapshot.children
{
self.nameList.append((child as AnyObject).value)
}
})
So here my database looks like this: (picture is cut off but there's no children under it)
Yet somehow when I print snapshot I get:
Snap (Employees) {
0 = "";
1 = "name1";
2 = "name1";
}
This has been frustrating me for a while, it seems like it could have something to do with old snapshot values somehow being stored locally or somehow not seeing the most up to date version of the database. If it matters I have similar calls to .observeSingleEvent in this file, the one copy and pasted above is nested within another. Even if it were a synchronization problem, I still don't know how that could make the printed value the old value.
Any help would be so so appreciated.
This behavior is apparently by design. It's so strange that I actually contacted Firebase Support about it, and was told that they'd consider revising either the behavior or the docs, but couldn't promise a date and I should monitor their Release Notes URL for updates to it.
It makes a little sense if you consider it from the SDK point of view. You're calling observeSingleEvent. To Firebase this means they should only call you ONE TIME. Developers would probably find it confusing if a method with that name produced more than one callback, right?
But if you have persistence enabled things get a little weird. Just like with observeEventOfType, Firebase will give you the on-disk value immediately so you get the fastest UI update, but then it will call the server for a fresher value to be sure it has the latest data from then on. The problem is, since you're telling it not to call you back with this data, it will remember it (so you WILL see it in the future, which is why it seems confusing) but not tell you that it's arrived.
What I've discovered through some trial and error is that the instinctive drive to use observeSingleEvent may be misguided with Firebase anyway. Both iOS and Android uses "recycler" view mechanisms for table/collection views such that only a handful of items are actually in-memory at a time anyway, even on screens with a lot of data. Beyond this built-in efficiency from the platform, Firebase itself seems to work just fine even managing many dozens of in-memory refs at a time. In my apps, I've taken to just using observeEventOfType for all of my use-cases except where I have a very specific, and not theoretical-efficiency-related reason, to use observeSingleEvent. The app performance has been minimal, and the data then works much more the way you expect.

CloudKit 'Unexpected Server Error' Anytime Manual Operations Performed in Dashboard

I have been developing an iOS app that utilizes the CloudKit feature available for Apple Developers. I've found it to be a wonderful resource, especially since the very day I started designing my backend, the service I was intending to use (Parse) announced it was shutting down. It's very appealing due to it's small learning curve, but I'm starting to notice some annoying little issues here and there so I'm seeking out some experts for advice and help. I posted another CloudKit question a couple days ago, which is still occurring: CloudKit Delete Self Option Not Working. But I want to limit this to a different issue that may be related.
Problem ~ Ever since I started using CloudKit I have noticed that whenever I manually try to edit (delete an entry, remove or add part of a list, even add a DeleteSelf option to a CKReference after creation), and then try to save the change, I get an error message and cannot proceed. Here is a screenshot of the error window that appears:
It's frustrating because anytime I want to manipulate a record to perform some sort of test, I either have to go do it through my app, or just delete the record entirely and create a new one (that I am able to do without issue). I have been just working around this issue for over a month now because it wasn't fatal to my progress. However, I am starting to think that this could be related to my other CloudKit issues, and maybe if I could get some advice on how to fix it I could also solve my other problems. I have file numerous bug reports with Apple, but haven't received a response or seen any changes.
I'd also like to mention that for a very long time now (at least a few days), I've noticed down in the bottom left hand corner of my Dashboard that it is consistently saying that it's "Reindexing Development Data". I remember at first that wasn't an issue, I would get that notification after making a change but it'd go away after the operation is complete. Now it seems to be stuck somewhere inside the process. And this is a chronic issue, it's saying this all the time, even right when I log into my dashboard.
Here is what I'm talking about:
As time goes on I find more small issues with CloudKit, I'm concerned that once I go into production more problems could start manifesting and then I could have a serious issue. I'd love to stick with CloudKit and avoid the learning curve of a different service like Amazon Web Services, but I also don't want to set myself up for failure.
Can anyone help me with this issue, or has anyone else experienced it on a regular basis? Thanks for the advice and help!
Pierce,
I found myself in a similar situation; the issue seemed to be linked to Assets; I had an Asset in my record definition. I and several other I noted reported the re-indexing issue on the apple support website and after about a month it eventually disappeared.
Have you tried resting your database schema completely, snapshot the definition; since you zap it completely and than reset, see inset.
Ultimately I simply created a new project, linked it to cloud kit and use the new container in my original app.

CoreData between app updates, signal a default-data refresh

when dealing with CoreData, I've run into a few problems I'm trying to nip in the bud for future proofing the system out of the gate. The simple fact of the matter is that I've never done anything like this before (work with CoreData that is). While I've managed to figure out how to work with it in the app, I need to know a decent practice to signal an app between versions that default data needs to be refresh on first app launch.
So right now, in my AppDelegate, I setup my managed object context, and I perform a fetch request to see if there are any records at all in a particular table/entity. I only want this to happen on first launch so im not constantly rewriting the contents of the DB every app launch. Anyways, so it goes ahead and uses Object Models to handle inserting of data amongst the entities in question (theres a few)
Now, for this version of the app, it's going into the store without an API (thats a far future thing), but between versions released to the app store, we may have to update specific information within the entities (for example: prices), again I only want this refresh to happen on app launch. Also, the schema MIGHT change, Im not sure if or when, but I'd like to make sure this can accomodate that just in case.
I figured, versioning the coredata "Add Model Version" would do the trick, set the new db version as the active version, but when I launch the app in the simulator, nothing happens which tells me that the data inside is being retained.
Any help towards what it is that I should do to accomodate this would be appreciated. Thank you!
You should find the Core Data Model Versioning and Data Migration guide useful:
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreDataVersioning/Articles/Introduction.html
You'll also probably find Method for import initial data with coredata useful.

Resources