Skip to end of metadata
Go to start of metadata

This documentation is no longer actively supported and may be out of date. Going forward, please visit and bookmark our new site ( for up-to-date documentation.

Version 3.1.1 and newer


Mapping SDK 3.0 Integration Guide (iOS)


Mapping Setup and Prerequisites

iOS Managed Provider Setup

  • Phunware recommends using CocoaPods to integrate the framework. Simply add pod 'PWMapKit' to your podfile.
  • Alternatively, all of the following frameworks can be added to the Vendor/Phunware directory of your project:
    • PWMapKit.framework
    • PWCore.framework
    • PWLocation.framework
  1. Initialize Cocoapods if your project does not already use it. If your environment does not already have Cocoapods installed, enter "sudo gem install cocoapods" in Terminal. After Cocoapods is installed, navigate to your project's root directory in the Terminal. Enter "pod init" in Terminal.
  2. In the Podfile file that is generated, modify the text in Xcode or your preferred text editor. Add the line "pod 'PWMapKit'" after the "target" line and before the "end" line. Save the file.
  3. Enter "pod install" in Terminal while in the directory that contains the Podfile.
  4. Use the .xcworkspace file that was generated by the pod install from now on.
  5. In your project's Info.plist file, add a row with key: "Privacy - Location When In Use Usage Description" (Xcode should autocomplete this) and for value, add what you want your users to see when prompted for Location use by the device.


Additional Documentation


PWMapKit uses the following third-party components. All components are prefixed so you don't have to worry about namespace collisions.

SVPulsingAnnotationViewA customizable MKUserLocationView replica for your iOS app.MIT


Sample Application

The framework comes with a ready-to-use sample application. In order to use this application you will need to update the configuration with your MaaS credentials and location provider information.

  1. Update your MaaS credentials and set up the building identifier in BuildingConfiguration.plist.



The primary use of the components of PWMapKit revolve around creating a map view, displaying points of interest, showing the user's location and indoor routing.

The example shows how to instantiate a PWMapView and load a building from the sample application, where "mapView" is a PWMapView property of calling class.


Load Building
self.mapView = [[PWMapView alloc] initWithFrame:CGRectZero];
self.mapView.delegate = self; // self must conform to <PWMapViewDelegate> protocol
__weak typeof(self) weakself = self;
[PWBuilding buildingWithIdentifier:<#buildingIdentifier#> completion:^(PWBuilding *building, NSError *error) {
    if (building) {
        [weakself.mapView setBuilding:building];


Register Location Provider

The PWMapView can display a user location on the map if a location provider is registered with the PWMapView.

The location providers are in the PWLocation framework, and each different provider requires different steps to set up.

(See Readme at to view setup examples of all different provider options).

Once the location provider is initialized, the call may be used to register the provider with the PWMapView.

Set Map Location Type
[mapView registerLocationManager:<managerObject>];


Indoor Location

The indoor location is provided by the PWLocation framework and can be accessed via the "userLocation" property of PWMapView.

Indoor Location
PWCustomLocation *userLocation = self.mapView.userLocation;

Routing for iOS Mapping

Calculate Route

Simply feed the PWRoute class method two points of interest and whether or not accessibility should be considered when calculating the route.

accessibility:YES will not use access points marked as "inaccessible" in the portal, e.g. stairs between floors.

Calculate then show route.

Calculate then show route
__weak typeof(self) weakSelf = self;
[PWRoute initRouteFrom:<#(PWPointOfInterest *)#> to:<#(PWPointOfInterest *)#> accessibility:<#(BOOL)#> completion:^(PWRoute *route, NSError *error) {
    [weakSelf.mapView navigateWithRoute:route]; // will begin routing in PWMapView


Current Route Updates

As a user traverses a route, PWMapKit will post notifications to tell the developer when the next routing instruction is reached.

Routing Updates
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(myInstructionUpdatedMethod:) name:PWRouteInstructionChangedNotificationKey object:nil];


Managed Provider

Displaying your Map

Step 1

In your AppDelegate.m implementation, add the following line to your "- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions" function, replacing the parameters with your App values, found on the MaaS portal.

Leave "encryptionKey" as an empty string.

[PWCore setApplicationID:@"YOUR_APP_ID" accessKey:@"YOUR_ACCESS_KEY" signatureKey:@"YOUR_SIGNATURE_KEY" encryptionKey:@""];

Step 2: 

In the view controller that you wish to add the map view, add the following the top of the file.

#import <PWMapKit/PWMapKit.h>

Step 3: 

Add a PWMapView as a property of your view controller's "@interface":

@property (nonatomic, strong) PWMapView *mapView;

Step 4:

Add the PWMapViewDelegate protocol to your view controller:

@interface ViewController () <PWMapViewDelegate>

Step 5: 

The PWMapView will stretch to fit the entire superview for this example.

In your view controller's `-(void)viewDidLoad` function, add this code.

self.mapView = [PWMapView new];
self.mapView.delegate = self;
self.mapView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:self.mapView];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.mapView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.mapView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0.0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.mapView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0.0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.mapView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0.0]];

Step 6:

To load your building, add the code snippet, using your building identifier found on the MaaS portal.


NOTE: The "dispatch_async" is currently required because of an internal SDK bug that will be fixed in the next release of PWMapKit/PWLocation.
__weak typeof(self) weakSelf = self;
[PWBuilding buildingWithIdentifier:YOUR_BUILDING_IDENTIFIER completion:^(PWBuilding *building, NSError *error) {
    dispatch_async(dispatch_get_main_queue(), ^{
        [weakSelf.mapView setBuilding:building];


Showing Current Location on the Map 

This will display your current location on your building map if the MaaS and hardware were also configured properly. If you encounter issues, create the PWManagedLocationManager as a property and assign its delegate to your view controller rather than calling registerLocationManager on the PWMapView. The error may then be captured with the PWLocationManagerDelegate callback function "- (void)locationManager:(id<PWLocationManager>)manager failedWithError:(NSError *)error;"


Step 1:

At the top of your view controller add this code.

#import <PWLocation/PWLocation.h>

Step 2:

Modify the building load completion block so that it looks like this.

Insert your building identifier in the denoted locations. 

NOTE: The dispatch_async use is to workaround internal SDK issues which will be fixed in the next release of PWMapKit/PWLocation.
__weak typeof(self) weakSelf = self;
[PWBuilding buildingWithIdentifier:YOUR_BUILDING_IDENTIFIER completion:^(PWBuilding *building, NSError *error) {
    dispatch_async(dispatch_get_main_queue(), ^{
        [weakSelf.mapView setBuilding:building];
        PWManagedLocationManager *managedLocationManager = [[PWManagedLocationManager alloc] initWithBuildingId:YOUR_BUILDING_IDENTIFIER];
        dispatch_async(dispatch_get_main_queue(), ^{
            [weakSelf.mapView registerLocationManager:managedLocationManager];

Step 3: 

Add a property to your view controller.

@property (nonatomic, assign) BOOL isFirstLocationUpdate;

And in "- (void)viewDidLoad", set isFirstLocationUpdate to YES.

self.isFirstLocationUpdate = YES;

Step 4:

Add the delegate callback to your view controller that the PWMapView's delegate is set to.


NOTE: This workaround will be unnecessary in the next release of PWMapKit/PWLocation (3.1.2 and newer). Any mechanism you would like to use to only set the tracking mode once is fine.
- (void)mapView:(PWMapView *)mapView locationManager:(id<PWLocationManager>)locationManager didUpdateIndoorUserLocation:(PWIndoorLocation *)userLocation {
    if (self.isFirstLocationUpdate) {
        self.mapView.trackingMode = PWTrackingModeFollow;
        self.isFirstLocationUpdate = NO;


  • No labels