0

I'm working with an app utilizing RestKit (which may or may not be relevant to the issue I'm having) in which the app wakes up for a few seconds after certain intervals and makes a managedObjectRequestOperation to a server. This works perfectly all day long, but typically between about 1am and 7am when my device is sitting charging having not been used in a few hours the request gets sent but I'm not registering any sort of response.

The requests don't seem to be timing out or any other similar errors, my logs print that I'm sending a request and then nothing happens at all, no response, no error... Does the phone go into some sort of coma-mode overnight? My device is an iPhone 5 running iOS7.

EDIT:

What I was basically doing is sending a request to a server and updating core data with the results, which then updates a tableView. My original implementation basically sent an NSNotification to the app, which tells a tableview to send a request and update itself according to the results, similar to this:

-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    [[NSNotificationCenter defaultCenter] postNotificationName:@"RefreshData" object:nil];

    completionHandler(UIBackgroundFetchResultNewData);
}

When really it should be doing this:

-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    [RefreshDataWithCompletionHandler:(void (^)(id result))completionHandler {
         // handle updating the data here based on the result of the request to the server
         ......

         // then call the completion handler here
         completionHandler(UIBackgroundFetchResultNewData); 
   }];
}

Is that a more accurate representation of the correct steps?

Marco
  • 6,692
  • 2
  • 27
  • 38
Mike
  • 9,765
  • 5
  • 34
  • 59
  • Unlikely to be RestKit related probably, though it doesn't use iOS 7 sessions... How are you triggering the app to run in the background? – Wain Jan 28 '14 at 17:00
  • Using the background fetch mode calling performFetchWithCompletionHandler – Mike Jan 28 '14 at 17:56
  • And you're calling the completion handler in the success block called by RestKit? And your requests take less than 30 seconds? – Wain Jan 28 '14 at 18:23
  • When the app is backgrounded normally during the day, and performFetchWithCompletionHandler is called, the request/response time is less than a second. As of right now, in the completion handler I broadcast an NSNotification that basically kicks off the restkit request. – Mike Jan 28 '14 at 19:11
  • In the completion handler? You should trigger the request immediately and call the completion handler when the response is received and processed. – Wain Jan 28 '14 at 20:30
  • Looking through the code, what is basically done (omitting some other stuff) is we first post the notification that I should do the request and on the next line call completionHandler(UIBackgroundFetchResultNewData); The issue you're explaining definitely sheds light on what the issue is here - but I suppose my question is why does it *sometimes* work? Maybe it's just a timing issue, and maybe sometimes when completion handler is called it just basically kills whatever was about to happen, including the request response? – Mike Jan 28 '14 at 21:53

1 Answers1

2

From the discussion, it sounds like the issue is with how the request is made and the relationship to the completion handler. When performFetchWithCompletionHandler: is called the request should be started immediately (posting a notification is fine for this as it runs inline). The request should complete within 30 seconds and then the supplied completion block should be called after the received data has been processed (so in the RestKit success block).

If you call the completion block too soon the app will be terminated, either before the request is sent (it's asynchronous) or before any response is received (it will just be ignored).

Wain
  • 118,658
  • 15
  • 128
  • 151
  • I see exactly what you're saying. I added some code to show what I was originally doing and what (basically) I'm doing now with your advice. Is the code I added more in line with the correct implementation? I'm assuming that overnight maybe the requests simply take longer as the phone is asleep so they never get a chance to process the response as the completion handler kills it pretty much right away, but it works during the day because it's maybe faster while the phone is semi-active? – Mike Jan 28 '14 at 22:46
  • Code looks better. Not sure about the difference between night and day. The system does learn from previous requests so it could be shortening the available time. Note also that you shouldn't always say new data was available (I.e. If no new data was available) as it will affect the learning algorithm. – Wain Jan 28 '14 at 22:52
  • One more question on that note - when I make the requests to the server, information on the server is updated and it's important the server knows the device basically "checked in"... Will always returning new data in the handler make these requests happen more or less frequently? – Mike Jan 28 '14 at 22:57
  • 1
    Apple don't publish details of the learning algorithm, it is based on a number of factors including user usage, failure rate, time taken... The goal is to provide data just before the user needs it, not to allow the app to check-in periodically. – Wain Jan 28 '14 at 23:33