08 Traffic information
Overview
In this tutorial, you will learn how to retrieve traffic information from the PTV NavigationSDK.
Base
Use Tutorial07
as a starting point for this project.
Obtaining a key
For using the traffic information functionality in the sdk, you will need an API key. Please contact the PTV Navigator product management to obtain such a key (if you haven't already got one) and set the key with [NSDK_Navigation setTrafficSearchWebConfiguration:token:]
in the AppDelegate application:didFinishLaunchingWithOptions:
method.
@implementation AppDelegate ... - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { ... // Uncomment the following line and replace <TOKEN> with your PTV Traffic Token if you want to use traffic //[NSDK_Navigation setTrafficSearchWebConfiguration:@"http://ti.ptvgroup.com/wfs" token:@"<TOKEN>" error:&error]; ... }
Retrieving traffic informations
To retrieve traffic informations, we have to call [NSDK_Navigation searchTrafficInformationWithPosition:observer:error:] with the current GPS position. This will trigger an asynchronous call to a traffic REST service. For getting notified when the traffic request is finished, we implement the NSDK_Observer protocol and pass self
as the observer parameter. Because we want to fetch traffic updates repeatedly, we call it in the navigation loop every X times the loop is running.
@interface NavigationLoop : NSObject <NSDK_Observer>
@interface NavigationLoop () { BOOL _isNavigation; int loop; } ... @end @implementation NavigationLoop ... //NSDK_Observer protocol implementation - (void) onFinished:(NSError*) error jobid:(int) job { if (error.code == 0) { dispatch_async(dispatch_get_main_queue(), ^{ NSError *err; NSArray * arr = [NSDK_Navigation getTrafficSearchResults:&err]; if (err == nil) { for (NSDK_TrafficSearchResult * trafficSearchResult in arr) { NSLog(@"TrafficSearchResult: %@", [trafficSearchResult getDescription]); } } }); } else { NSLog(@"NSDK_Observer finished with errorcode:%ld text:%@", (long)error.code, error.localizedDescription ); } } - (void) _run { loop++; NSDK_GPSData * nsdk_gpsdata = [[NSDK_GPSManager sharedInstance] getCurrentPosition:nil]; if (nsdk_gpsdata != nil && [nsdk_gpsdata getFix] >= 0) { ... if (loop % 10 == 0) { //fetch traffic information every 10th time we got a valid GPS Position loop = 0; NSError * err; [NSDK_Navigation searchTrafficInformationWithPosition:[nsdk_gpsdata getGPSPositionMerc] observer:self error:&err]; if (err) { NSLog(@"searchTrafficInformationWithPosition called, error:%@", err); } else { NSLog(@"searchTrafficInformationWithPosition success"); } } }
Attention
The call to [NSDK_Navigation searchTrafficInformationWithPosition:] returns immediately because it's asynchronous. Use the NSDK_Observer for obtaining the traffic incidents.
The NSDK_Observer implementation is used for getting traffic information as soon as the previously triggered search has finished. This observer has one major function that we override: onFinished
. (It has also a method onProgress
, but we do not need this method in this chapter). At this stage, we call [NSDK_Navigation getTrafficSearchResults] to fetch the actual result and do a NSLog.
Attention
The call to [NSDK_Navigation getTrafficSearchResults] has to be wrapped in a 'dispatch_async' block, so that it's executed in a different thread. Doing otherwise would result in a deadlock because the SDK can't handle a call to a SDK function within a SDK callback function in the same thread.
In order to make requests to the REST interface of the PTV Trafficserver work, you have to allow HTTP Requests in your Info.plist by defining the following keys/values:
- Define a key "App Transport Security Settings" with type "Dictionary".
- "Allow Arbitrary Loads" with value "YES" as a member of this Dictionary.
In our Tutorial08 XCode Project, we have implemented a simple UIViewController (TrafficTableViewController
) with a UITableView to display the traffic incidents. The TrafficTableViewController gets displayed, when a Button at the top of the ViewController is pressed.