How to load the PersistentStores in a correct way? - swift

I've been looking on Internet the entire weekend and today on how to handle correctly any error when the PersistentStores loads, without a success!
Actually, so many people are looking for the same solution but no one gets an answer. For example: https://www.hackingwithswift.com/forums/swift/core-data-error-checking/3794
Apple give us a fatalError in their template while telling us to not use it for a shipping application.
Here's also how you can have it, from many tutorials on Youtube, for example:
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error {
print("Core Data failed to load: \(error.localizedDescription)!")
}
print("Core Data succeed to load!")
})
As I'm not able to handle a potential error, because I still don't know how to do it, I'd love to just load it without handling any error ; but I can't just delete the if and the print and leave it blank. So, what should I put inside?

The question doesn't have a straightforward answer because what you do depends on what your app does and how you want it to respond in this situation. Every app's requirements are different, and you have not given any indication of yours.
If this error happens, your app has failed to load the persistent store. Whatever data might have been in that store is not available. New data cannot be saved to that store. What should you do? What can you do, in your app, to meet your requirements? What do you want your app to do if this persistent store is not available? What would you consider to be a reasonable response, in your specific app? That is what you do here.
There's no real recovery path; you can't simply make the error go away. You could try deleting the old persistent store and creating a new one. That would lose any previously saved data. Is that OK? It depends on you and your app. If you want to do that, look into the destroyPersistentStore(at:, type:, options:) function to remove it cleanly. Then try loading the store again, and a new one will be created.

Related

Ways of handling serious problems on an iPhone app

Say you are doing something critical to the app's usability at startup (like copying the SQLite DB or setting up CoreData) and something goes wrong that doesn't cause a crash but you don't want the user to continue. What can you do?
Currently my app has abort() and NSAssert(false,...) calls to make sure the app doesn't continue, obviously after the error has been logged. But somehow I think its not going to score points with Apple on the app store.
Anyone have any ideas what I can do in such situations? I understand for instance that if there is no connectivity you can put your app in 'offline' mode but lets say the DB couldn't be properly setup (for argument sake). There is no 'offline' for that and so the user cannot continue. The user needs to quit the app and try again or report the problem. Wouldn't you agree, or am I missing something?
I just decided to create a view that has a message on it explaining to the user that a critical error has occurred and explained some steps to follow to resolve it. It prevents the user from using the app until it is resolved. So if the DB is missing or the model schema doesn't match the DB schema it will bring up that view.
Its one way of doing it that I took. If anyone has a different way, I'd like to hear it.

When is it best to do an NSManagedObjectContext save?

I have noticed that for a mobile application, saving on the main thread seems to take a bit when it compares to other applications on the device. Is it recommended to only save Core Data when the application enters the background or when an application closes instead of anytime items are added and sent / received from the api?
That's kind of a broad question, but I've found that saving core data after VewDidAppear statements is better than viewWill statements. Giving the user something to engage with and persisting makes it less noticeable than on a load. However, if a user is used to waiting for something like an activity loop, adding the save to that doesn't tax it too much (IMHO).
Not sure this help, just my experience.

iOS core data corruption?

This is a rather general question, as I don't have any solid evidence atm.
I have an iPhone app with about 20,000 users. It allows users to message each other, and saves those messages in core data. The only other thing it saves in core data is the users profile, a copy locally and a copy on the server.
I have a small percentage of users complaining that they receive messages but nothing shows, when they send a message (which immediately goes into core data then shows on screen) it disappears immediately. Nothing but a full restore seems to fix it, and from what I can gather, even a restore which involves them restoring a backup they just made doesn't fix it.
My first thought was that core data must have become corrupted in some way ... but the messages they attempt to send actually do send, and this would be impossible if their local profile had become corrupted too.
I've never been able to recreate it, or found anyone face to face who has had a similar problem.
Does anyone have any suggestions on what could occur in core data that could lead to a situation like this so I can start to try and track down the problem? I'd estimate it's happening with about 1% of users.
Once again, sorry for the generality of the question, but it's all I have to work with just now!
Thanks
** Edit
Just to clarify, deleting the app and reinstalling it, does not fix the problem when this happens.
** Edit
I just had some more information from a user who is suffering from the problem ... the information my app saved in core data still exists after the app has been deleted and re-installed, all of it. I have deleted and re-installed my app hundreds of times over the last year, on countless different devices, and every time I delete and re-install, all previous data stored in core data is completely erased .. yet for these users, this is not happening. Does this sound like an iPhone issue that basically requires a restore?
** Edit 03/12/2010
AT LAST! I have some real solid information to work on. I added flurry to my latest release so I could track any core data error messages, and was able to correlate the errors received with a user id that I knew for a fact was experiencing the problem ...
The error is: "Msg: Error Domain=NSCocoaErrorDomain Code=133020 'The operation couldn’t be completed. (Cocoa error 133020.)' UserInfo=0x39c7c0 {conflictList=( 'NSMergeConflict (0x39c700) for NSManagedObject (0x38ad00) with objectID '0x375c30
Unfortunately, the error is trimmed. Flurry must have limit on the size of the message it can pass.
I don't have access to my mac and code just now, I'll start investigating as soon as I do and post back with some source code and any findings I have.
I'm having a problem like that right now. So far I have figured out that the same object is modified in two NSManagedObjectContext-s. The object X has (at least) two persistent attribites, a and b, one thread changes a, another thread changes b, and CoreData cannot merge.
The key phrase in the error message is NSMergeConflict:
Error Domain=NSCocoaErrorDomain Code=133020 "The operation couldn’t be completed. (Cocoa error 133020.)" UserInfo=0x1544c7d0 {conflictList=(
"NSMergeConflict (0xc489f40) for NSManagedObject (0xd833ca0) with objectID '0xd82b7c...
Not sure this really helps, but at least it tells you what might go wrong...
Does anyone have any suggestions on what could occur in core data that could lead to a situation like this so I can start to try and track down the problem?
About a zillion different things.
Your real problem is that you are trying to debug in a speculative fashion. To properly fix this bug, you first need to know how to reproduce the bug. There's no other way to know if you've fixed it after you've tried something.
I would not start by blaming the underlying frameworks like Core Data. Odds are your program is the one losing the data. Start with that assumption.
Does it affect these users from the moment they set up there account? Could it be something to do with their username/id/personal information?
If deleting the app completely and reinstalling doesn't solve the problem, then I'm at a loss for how it could be core data - as you yourself say, I often do this and it removes all core data each time. So if it is core data corruption, it would have to be in your construction of the core data instead of the database itself. I don't think it likely that only people who install your app would have problems with core-data being retained.
If you have contact with a user experiencing this problem, I would get them to try to create a new username that is "safe and normal".
Good Luck.

Problem in adding values to the database when apps will terminate

I have to save my application data so i am adding all the database while application quit and when apps open, i am retrieving all the records.
It works perfect only for two times means first apps installed, it will save data for app termination 1 and apps termination 2. But then after it doesn't save my data to the database or third time termination. I checked that all values are coming and everything goes fine, but it is not saving for third time termination . There is not error message also.
Does anyone face this problem? Can any one guide me?.
Thanks,
iPhone Dev.
Have you tried saving to a log file to see that the db saving completes. Something like
Write to file ("save started")
... call the save
Write to file ("save ended")
This way you can discover if this code is (A) called at all, or (B) fails half way through.

iPhone Core Data application will terminate save database required?

I have an application that allows you to edit some percentages, however it will only let you commit those changes if the percentages add up to 100. However because the Core Data template includes the save code in the application will terminate. If the user changed something and then exited the application, the item would be of course saved even though it did not add to a 100%.
Therefore I simply decided to comment out the save in the application will terminate. I know the other option would be to use another context for the edit and then merge the changes or setting my context values until the actual save point. However I do not see any harm in commenting out this line, since I save whatever I want in my application when the user clicks the save button, so my question is: is the save on the application will terminate mandatory? what possible consequences could this have?. It is important to note that the application continues to work just fine after commenting this lines (which is what I expected).
Thank you in advance.
-Oscar
You can save whenever you like.
However, you will never know when the app will terminate. Unlike applications on more conventional platforms e.g desktops, the iPhoneOS will terminate your app (from the apps perspective) at random. The only warning you will get will be the applicationWillTerminate message sent to the app delegate. If you don't handle saves there then it is highly likely that at some point, your users will lose data.
I think you should reconsider your design. It sounds like you're putting calculation into the managedobjects that could (1) be handled elsewhere in code or (2) be handled by transient properties. You shouldn't have a condition in which the managedobject can't be saved at the drop of hat. Doing so makes your datamodel utterly dependent on external code for its internal integrity. This causes problem with maintenance, portability and upgrading.
Its not mandatory to save on application will terminate. You can save when ever you feel appropriate for the context of the app.