Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MKDirections many requests stop working

I need to draw a path starting with a list of coordinates (P1, P2, ... Pn). For each next couple Pi, Pj of my list I call the method calculateDirectionsWithCompletionHandler of the class MKDirections until the Pn-1 element. The first time I call it everything looks perfect. But if I call a second time or further I got this error:

Error Domain=MKErrorDomain Code=3 "Directions Not Available" UserInfo={NSLocalizedFailureReason=Route information is not available at this moment., MKErrorGEOError=-4, MKDirectionsErrorCode=2, NSLocalizedDescription=Directions Not Available}

and nothing works anymore.

I think this happens because I call the API too many times in a short time. I found on the web I should use the attribute direction.calculating and check if a request is already in progress. I cannot understand how to use it. Anybody can help me? Thank you.

like image 812
cicaletto79 Avatar asked Dec 21 '15 16:12

cicaletto79


1 Answers

I experienced the same doing a unit test.

What I usually do with such APIs is using a rate limiter. It limits the number of calls to an API in a given timeframe.

There are several implementations, I successfully use and like this one https://github.com/nuclearace/SwiftRateLimiter

It lets you choose the number of calls and the timeframe. (You can even use two instances for one API so say: at most 10 calls per second and at most 100 calls per minute)

I don't like the direction.isCalculating approach too much, because it makes synchronizing your threads hard for the general case. A simple approach is to wait for an answer before making the next call. after you got the answer, directions.isCalculating obviously is false.

But I prefer the rate limiter.

Apple is throttling "poorly written/misbehaving Apps", but I'm not aware that Apple documented the rate limit it uses to do so.

code example:

let GlobalDirectionsRateLimiter = RateLimiter(tokensPerInterval: 3, interval: 1.0)


GlobalDirectionsRateLimiter.removeTokens(1) {_,_ in
    directions.calculate { (response: MKDirections.Response?, error: Swift.Error?) in
    ...
    }
}

Don't trust my parameters for the rate limiter. All calculations in my app come from user actions, so I don't need more.

like image 88
Gerd Castan Avatar answered Oct 08 '22 14:10

Gerd Castan