0

I got an app which stores data about restaurants. Their menu, schedule and so on. Theres ~200 restaurants in the DB by now. The app used to retrieve those places by a single shot, but it was taking too much time to load, so i decided to load the data one by one. On the start app asks the server for an array of place's ids, then get the data via API.

I set completion blocks for RK's operations to background queues, but it didn't help. Scrolls are running not smoothy enough and sometimes the app even deadlocks(sic!) or crashes with no error output in the console. I've tried using Instruments to locate what makes UI go jerky, but didn't succeed. I even turned off image loading and sorting functions. I used to have RK's requests calls wrapped in @synchronized, so i removed it, but no effect.

Never thought i'd be facing this kind of issue after few weeks of experience with objective-c. I've tried every possible way that came to my mind, so now im kinda giving up.

Please help me :)

The code below gets called 200 times right after the app start.

NSURLRequest *request = [[DEAPIService sharedInstance].manager requestWithObject:nil
                                                                              method:RKRequestMethodGET
                                                                                path:path
                                                                          parameters:params];
    //DLog(request.URL.absoluteString);

    NSManagedObjectContext *context = [NSManagedObjectContext MR_contextWithParent:[NSManagedObjectContext MR_contextForCurrentThread]];

    RKManagedObjectRequestOperation *operation = [[DEAPIService sharedInstance].manager managedObjectRequestOperationWithRequest:request
                                                                                                        managedObjectContext:context
                                                                                                                         success:success
                                                                                                                         failure:failure];

    // dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
    dispatch_queue_t backgroundQueue = dispatch_queue_create("com.name.bgqueue", NULL);
    operation.successCallbackQueue = backgroundQueue;

    [[DEAPIService sharedInstance].manager enqueueObjectRequestOperation:operation];

Response descriptors are set before that. And also there's many relations in the DB. I've looked up the DB's file size - it's ~1.5Mb. I wonder what will happen if there would be over 1k restaurants. Is it a good way to load this kind of data? What are the best practises?

Alexander
  • 11
  • 4
  • How did you come to using RK & MR this way? – Wain Apr 07 '15 at 06:48
  • Is there a reason you're using MR, and a reason you create a queue the request operation yourself? – Wain Apr 07 '15 at 08:28
  • Im not the author of the app, so i dont know why the previous guy did it that way. I checked out MR's code and it's just initialising a child context with concurrency type NSPrivateQueueConcurrencyType. MR is used all over the app, i suppose for convenience, cuz, for example, you can obtain first object in DB by a single line of code: APPlace *place = [APPlace MR_findFirst]; – Alexander Apr 07 '15 at 09:56
  • And how about your RK usage? Are you using an object manager to control the whole process and is RK tied into the Core Data stack fully (or is that why the context shuffle is being done)? – Wain Apr 07 '15 at 09:58
  • @Wain Im not quite familiar with RK, so i can't tell if it's "fully tied". property "manager" of DEAPIService is RKObjectManager. I suppose it's tying up by this code: https://gist.github.com/anonymous/274b038db7482f21b320 – Alexander Apr 07 '15 at 10:52

1 Answers1

1

Ok, from the information provided you should be able to simplify a lot. At the moment your code is dropping down to a low level and getting involved in threading and context management that you want to leave for RestKit to sort out. You have a properly configured object manager and core data stack by the looks of things so you should let it do the work.

This means removing the request, context and request operation code and simply calling `getObjectsAtPath:parameters:success:failure:'. RestKit will then deal with all of the download and mapping in the background and save the context.

You should also really be using fetched results controllers throughout your app, and if you are they will automatically detect the changes that RestKit has saved and update your UI.

Once you have that, any blocking of the UI is unrelated to RestKit and your download requirement and should be related to subsequent image management / downloads.

Wain
  • 118,658
  • 15
  • 128
  • 151
  • It partially helped, but still the scroll is a bit jerky. Where else could the problem be? Could relationships be involved? A single Place object got 4 of them. Here's a response descriptor setup: https://gist.github.com/anonymous/846599751c215a49acf5 And i do have a fetched results controller, even so i haven't got how it's actually fetched to the Core Data. I used to have UI updates on content changed, but it it was called to many times per sec, so i removed the reference. – Alexander Apr 07 '15 at 14:41
  • RK does all data processing in the background so unless you've flooded the CPU it won't cause UI lag. You should probably ask a new question which shows the code you have to update the UI when the FRC picks up a change. Profiling should also help you find the issue now. – Wain Apr 07 '15 at 14:44