3

I have an app which monitors significant location changes.
Upon receiving a new calculation I want to calculate the duration from the current location to a specified location.
To calculate the duration I use calculateETAWithCompletionHandler: from the MKDirections class.
Everything works as expected as long as the app is in the foreground.

When I send the app to the background, it is correctly receives location updates in the background and everything works until I call calculateETAWithCompletionHandler:, which will never return results.

MKDirectionsHandler, the completion handler of calculateETAWithCompletionHandler:. is never called when being in the background.

As soon as the app is coming into the foreground again, all the waiting completion handlers are receiving results.

MKMapItem* origin = [MKMapItem mapItemForCurrentLocation];
MKMapItem* destination = [[MKMapItem alloc] initWithPlacemark:destinationPlacemark];

MKDirectionsRequest* request = [MKDirectionsRequest new];
[request setSource:origin];
[request setDestination:destination];
[request setTransportType:MKDirectionsTransportTypeAutomobile];

MKDirections* directions = [[MKDirections alloc] initWithRequest:request];

[directions calculateETAWithCompletionHandler:^(MKETAResponse *response, NSError *error) {
        completion(response.expectedTravelTime, error);
}];

Is calling calculateETAWithCompletionHandler: in the background not allowed?
Is there any way to resolve this issue?

pre
  • 3,475
  • 2
  • 28
  • 43
  • 1
    I believe the way you are making use of `MKMapItem` is the problem, you need to run this on the main thread. So I don't think it will work for what you need. When collecting the location in the background you should use `CoreLocation` instead. – rmp Jun 02 '15 at 22:38
  • @rmp thanks for the hint. that seems to be the solution. if you post it as an answer, I'll accept it. – pre Jun 04 '15 at 11:59
  • Ok I will do that glad it helped solve your issue – rmp Jun 04 '15 at 14:12
  • @pre Were you able to find solution for background execution of "calculateETAWithCompletionHandler:" ? – AtWork May 17 '17 at 17:12
  • Any solution on this question? It is been around 4 years since the post was created and I am currently having the same issue. The directions.calculate runs on the main thread but returns null array when the app is in background state. Is it a Apple bug? – thus Oct 31 '21 at 18:13

2 Answers2

3

I believe the way you are making use of MKMapItem is the problem, you need to run this on the main thread. So I don't think it will work for what you need. When collecting the location in the background you should use CoreLocation instead.

rmp
  • 3,503
  • 1
  • 17
  • 26
  • 1
    The problem was the line `[MKMapItem mapItemForCurrentLocation]`, I had to use the location provided by `CLLocationManager` directly. – pre Jun 04 '15 at 21:18
  • Can you post some fixed code? I am stuck with the same problem. – AtWork May 17 '17 at 17:45
  • 1
    @AtWork My problem was `[MKMapItem mapItemForCurrentLocation]`. This method does not return in the background. Use `CLLocationManager` in the background to get the current location. – pre May 18 '17 at 11:19
  • @pre Thanks. Fixed the issue. – AtWork May 23 '17 at 19:41
0

The documentation around MKDirection is not very specific on this issue, the most relevant section I could find was:

An MKDirections object provides you with route-based directions data from Apple servers. You can use instances of this class to get travel-time information or driving or walking directions based on the data in an MKDirectionsRequest object that you provide. The directions object passes your request to the Apple servers and returns the requested information to a block that you provide.

Since you are trying to calculate travel-time, it would appear that calculateETAWithCompletionHandler: tries to perform a network request to the apple servers. With the application being in a background state, the request is put on hold until the application enters foreground again.

Unfortunately I don't think there is an easy way around this. You could try and use a "guesstimation" approach where, before the application enters a background state it calculates the ETA for a user, and then while it is in the background it increases or decreases the ETA proportionally to the direct distance between your current location and the destination. Depending on how precise you want your results to be this broad estimation could be enough to satisfy your requirements.

Danny Bravo
  • 4,534
  • 1
  • 25
  • 43
  • Do you have any documentation that `MKDirection` requests (or network requests in general) are put on hold while in background state? – pre May 28 '15 at 15:40
  • No, I don't but I know that if you want to make a request in the background you can either use a background session using NSURLSession or you have to wrap the network call in a background task, as per this answer: http://stackoverflow.com/questions/11864553/ios-http-request-while-in-background – Danny Bravo May 28 '15 at 16:12
  • Maybe you can try wrapping `calculateETAWithCompletionHandler:` in a background task? – Danny Bravo May 28 '15 at 16:12
  • You might want to file a bug report. – Danny Bravo May 29 '15 at 14:05