Application failed to resume in time : Core Data - ios

I am populating my core data with thousands of records in multiple entities one by one. This process is taking time to complete. This process is working fine when app is in active state. Once app goes in background and comes in foreground, the app is crashing with following error:
"failed to resume in time ios crash"
Please suggest some solution.
Thanks

The creating of the Core Data stack should never be done in the -applicationDidFinishLaunching If a migration is needed just inform the user about it but you need to return from the -applicationDidFinishLaunching... as fast as possible, you should only be creating UI elements in this method. You should not be accessing Core Data at this point.

You should not do very time-consuming tasks on the main thread. The crash is due to the populating process taking more than 10 seconds. It happened to me once in an infinite loop.
Start a new thread for this task, which will resume when your app enters foreground again. Tell the user what's going on, i.e. that the app is populating a database and that it may take some time. It is a good idea to show a progress indicator too.
As long as the user is kept well informed, he will accept to be patient.

Related

Best Life Cycle Method to Place Main Thread-Blocking Operation in Objective-C

My app syncs with a server similar to the Apple Mail app. While the sync takes place on a background thread, because it is hitting Core Data rather hard, I've found it necessary to block interaction with user controls during the sync, lest some other operation hit core data and create problems.
I had been putting the sync in View Will Appear to keep the phone and server in constant sync. However, with larger amounts of data, I'm noticing that the sync is unacceptably long...that is it ties up the thread for five or ten seconds. I tried placing it in viewdidload so it gets called less often but it is still annoying to wait when you have just opened app.
I've noticed that Apple does not sync mail immediately but waits a few seconds so as not to tie up the app at first. This gives you the illusion, you don't have to wait (although in reality you usually do).
I'm wondering if there is a place in the life cycle that would be better for syncing such as viewdidappear and also whether there is a way to use a delay to launch the sync five or ten seconds after you are in the view controller when it's less conspicuous.
Thanks in advance for any suggestions.
Firstly blocking the main thread isn't preferred under any circumstances for asynchronous operations , as the user will think that the app is hanging and will quit it
Secondly viewDidAppear is meant for updates when say it's in a vc that navigation returns to with back to refresh content or dismissing a model , other than those 2 things it will act like viewDidLoad with the overhead of delay
Finally if you need to sync the mails with server you have 2 options
grab data every fixed time ( not recommeneded ) say with a timer
use silent push notification to notify the app with server new content and initiating the pull process upon receiving it

Parse query on Main Thread

My iOS app relies heavy on server side data, and just for the launch of it, I need a little bit of information from Parse to get the job done on the app delegate... the issue is I'm making this query on the main thread because otherwise I would use a block or a queue, and immediately after the start of the app, the launch image shows up, then the query starts and the screen goes blank, then the query arrives and the app screen refreshes and is ready to go, but this looks very odd for the user experience and I don't want it to happen..
With the query on the main thread the launch image stays until the data arrives, and it looks much better and the loading time is about 2-3 seconds...
It feels like a bad practice, but...
Any advices?
Regards,
Miguel Rojas Cortés
Don't block the main thread when the app launches. If the network request isn't fast enough, the watchdog will terminate your app and your users will give you 1 star reviews.
Just display your UI with as much info as you have, and show some visual indication that more data is loading. Then update the views when the data arrives.
Also remember to handle the case that the user launches your app with no connectivity. The user should get an appropriate error and an option to retry.
You just need to do a bit more work here
Create a separate nib / view controller for the launch screen instead of the using the default iOS one
When the launch view controller loaded, starts the request, and don't do any transition just yet. Maybe show some kind of loading indicator there.
When all data has arrived, do a transition to the first screen (either fading smoothly or abruptly, IDK).
Doing query on main thread in this case may work 90% of the time, but the other 10%, eg when network is flaky, it's not a nice experience. The app will just hang there, and you got no chance to handle returned errors, since the main thread is blocked.

How long can core data migration take on startup?

I have seen successful core-data migrations of my 4Gb database on my iPad on application launch taking several minutes.
And now suddenly, some users report crashes after installing a new version and the app is kicked out with a: failed to launch in time error.
I just tested again by restoring an old database and I am sure that core data migration can take way more than 10 seconds.
But other people are concerned it should not and try to take it to the background, or at least out of the run loop at launch time:
iPhone app launch times and Core Data migration
Can this have anything to to with other conditions, e.g. being connected to a power source? Or have a battery level of more than 50 %?
Update: I reproduced a crash by just starting the app on the device (unplugged) instead of debugging.
Then I tried starting the app on the device with USB attached: Crash.
Then started the app via the debugger: No crash (and the migration took about 4 minutes.)
Extra info: I have only enterprise users (about 75 of them) and they all have a database of 4.5Gb. Some users have no problem upgrading and some have. The upgrades all take minutes if they succeed. The crashes always come after 20 seconds. (And they keep crashing if you try again on these devices).
I followed the advice to place the migration out of the run loop, but I am still wondering why the old method works on some devices and not on others. All users are on iOS 7.
This is a common launch problem. A Core Data migration can take any amount of time, 0 to N depending on the complexity of the model and the amount of data and the type of migration occurring.
Ideally you should not be creating your Core Data stack in the -applicationDidFinish... method and migration is one of the reasons.
My recommendation is to rework your launch so that you display something until the stack has initialized. This could be just your default image in a view. Then when the Core Data stack has initialized you can switch over to your full view controller stack.
I would also recommend taking this a bit further so that you can tell the user that a migration is in process and I would further put the migration on a background queue so that you can update the UI while the migration is happening.
Lastly, if you are doing a heavy migration, I would look into doing a lightweight migration instead. The lightweight migration is far faster as well as other benefits.
If you look at the crash log it will likely say that the app was killed because it took too long to startup. The watchdog process kills apps that take too long to startup - >20 seconds I think. This is because the core data migration process was run during app startup.
I'd recommend you manually run the migration in the background. The following new book on Core Data has code and explanation for how to do a background manual migration.
http://www.amazon.com/gp/aw/d/0321905768
It is not a rule that don't run migration on background thread, but its a suggestion because if you run on background thread and your app start running, it is not guaranteed that your core data stack will not touch.
You can take this migration out of the didFinishLaunching but make sure that stack is not touch. You can handle this by some check like place a viewController with message that app is updating which don't allow user to do anything, and at mean time you can perfrom background migration. When migration process finish you can simply dismiss that viewController take user to home viewController.
When your app is running on the iOS platform you can not gurantee every thing, like some time if native apps need more memory then memory will cut off from your app quota and can get some wired kills.

Ideal time to invalidate cached data in an iOS app

So I'm working on an iOS app which uses Core Data as a local, offline store for data stored on a remote server. Think like the way Mail.app keeps your most recent n messages. Now right now the app quite naively stores all of this data without deleting any of the old data.
My question is this: what's the best time in an iOS app's lifecycle to take care of tasks like removing cached data? I already know how I'm going to delete this old data, but doing so is an expensive operation. So what I want to know is when the best time to perform this sort of expensive operation is.
If it is not too much trouble, then doing so when the application goes into the background would be a nice time to do it. If it takes around 10 seconds or more, though, be sure to set up a background task to allow you to run for a bit more time.
You can run this operation in background with GCD or NSOperationQueue. I would do it after I get new data from server, then delete old cache, and build new one. If you move expensive operation to background (threads, block, NSOperation, or what ever you prefer) then it better to use child NSMagaedObjects for synchronization.

CoreData - when do I save?

I understand how to use CoreData, but I'm confused when it's best to save the data. When they press the home button? On every interaction in case the app crashes?
The reason why saving data is a separate call is so that you can batch multiple smaller changes that comprise a larger operation and save all at once, rather than saving at each step along the way.
You should save the data after each atomic operation, and never have committed data sitting only in memory for any significant period of time.
Each time the user commits a change to the data, they will expect the data to be there the next time they run the app, so it's your job to make sure it's there.
After your user submits a change to the data, your app is likely going to be waiting for the user do something else anyway, so save the data while the user decides what to do next.
If you wait to save data in the applicationDidEnterBackground, there is no guarantee that it will ever be called.
Obviously, not all data is critical, for example, data that a user has entered on a form, but hasn't submitted, is not critical. However, any submitted data is critical.
I don't think its a good idea to save on every interaction(Honestly your App shouldn't be able to crash on "every" Interaction ;) ).
I only save in my app in
- (void)applicationDidEnterBackground:(UIApplication *)application
In fact you are right regarding crashes. But what if an invalid Data causes the crash? So you will reload in the worst case the data so that it crashes every time.
But to be honest that is just an educated guess - I think it depends on how sensitive your Data/App is
edit: This answer provides a similar opinion Saving Core Data Context before Crashing
But there's is a really good point I missed:
you should save whenever the user performs critical operations
If you save in the background, you can do it very often without harming UX much. Remember though that you probably need to update you UI and that will have its impact (merge after save to main will be done on the main thread).
Keep you saves small (small number of objects) so not to stall the main thread.
it is very dependant on your CoreData stack architecture.
You will want to save on critical moments like entering background, or user important data/demand.

Resources