Saving master data and user interface performance

I am wondering if there are any recommendations for improving responsiveness to the user interface when performing Core Data savings (not retrieval) with large sets of managed objects.

The application I'm working on requires downloading a fairly large amount of data at set intervals from the web service to completion. At each interval, a data packet is loaded, formatted to managed objects, and stored in Core Data. Since this process can take up to 5 minutes until it is completely completed, simply adding a boot screen until everything is over is not an option, it takes too much time. I'm also interested in making frequent entries in Core Data, rather than one large entry at the end, to keep the memory level low. Ideally, I would like the user to be able to continue using the rest of the application in normal mode while simultaneously loading and writing these large datasets into Core Data.

Unfortunately, it seems that when I try to save my insertions, which I put in the context of the managed object for each batch, this save operation blocks the user’s interaction with the rest of the application (scrolling tables, touching a button, etc.) until it is completed. For those short periods of time when the master data is saved, the application is very unresponsive.

Naturally, I tried to make these reductions smaller by reducing the size of individual batches that load per interval, but in addition to the inconvenience of making the whole process longer, there will still be cases when the swipe user is not captured, because at that particular time the main data was saved . Downsizing just makes it less likely that missed wipes or missed touches will happen, but they still seem to happen often enough to be uncomfortable.

For the inserts themselves, I tried to use two different implementations: insertNewObjectForEntityForName: inManagedObjectContext, as well as setValuesForKeysWithDictionary. Both demonstrate the problem described above.

I tried prototyping a much simpler test to see the performance both in the simulator and on the device, important elements are presented here. This example does not actually download anything from the Internet, but simply writes a whole bunch of material to the main data at set intervals from the TableViewController. I would like to know if anyone has any suggestions for improving the reaction.

- (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(doTimerWork:) userInfo:nil repeats:YES]; } -(void) doTimerWork:(id)sender { for (int i = 0; i < 1000; i++) { Misc * m = (Misc*)[NSEntityDescription insertNewObjectForEntityForName:@"Misc" inManagedObjectContext:managedObjectContext]; m.someDate = [NSDate date]; m.someString = @"ASDASDASD"; m.someOtherString = @"BLAH BLAH BLAH"; m.someNumber = [NSNumber numberWithInt:5]; m.someOtherNumber = [NSNumber numberWithInt:99]; m.someOtherDate = [NSDate date]; } NSError *error; if (![managedObjectContext save:&error]) { NSLog(@"Experienced an error while saving to CoreData"); } } 
+4
source share
2 answers

It sounds like you need to dump your data using Core Data on a separate thread, which, fortunately, is pretty easy in Cocoa. You can simply:

 [obj performSelectorInBackground: @selector(method:) withObject: arg]; 

And then create things so that once this intensive operation is complete, call:

 [otherObject performSelectorOnMainThread: @selector(dataStuffIsDone:) withObject: arg waitUntilDone: NO]; 

At this point, you can update your interface.

The main thing to remember is that you always keep your user interface logic in the main thread, both for the right design, and because very strange things can happen if you do something with UIKit from another thread, as these are not designed to provide security streams.

+3
source

Usually you load your data into a background thread and insert / update managed objects into your managed object context.
In the main thread, you must register and get NSManagedObjectContextWillSaveNotification and use mergeChangesFromContextDidSaveNotification: to update the main context of the managed entity.

Is that what you do?

Also, read Multi Threading with Core-Data .

+6
source

Source: https://habr.com/ru/post/1300151/


All Articles