Introduction
Welcome to the Proximi.io iOS SDK reference. Use our library to hook into the new Proximi.io platform.
You can find the Android reference here.
Code samples can be found on the area to the right of this page.
Additionally, you can also find our new Proximi.io iOS MapLibre SDK reference here.
API Changelog
5.2.17 - 5.2.20
- Rework sync system
- Improved geofence exit handling
5.2.0 - 5.2.16
- New sync system
- Minor fixes
5.1.5
- MapStyle database entity
- Amenity category database entity
5.1.3
- Expose func to remove processors
5.1.2
- Improved token swap handling with auto-reset
5.1.0
- Improved performance for level handling
- Include support for Campus
- Introduce OSRMs
- Introduced
metadata
field in entities
5.0.1
- Unifying versioning between libs to correspoint to API version.
- Improved compatibility with iOS 13
- Fine tuning for the background operations in various situations
Quick Start
/// Obj-C Example
@interface TestViewController : UIViewController <ProximiioDelegate>
- (void)proximiioPositionUpdated:(CLLocation*)location {
NSLog(@"User position updated to: %@", location);
}
//Set the delegate and authorize
- (void)viewDidLoad
{
[super viewDidLoad];
/// force request permission with background, use NO if you don't need background
[[Proximiio sharedInstance] requestPermissions: YES];
/// start auth
[[Proximiio sharedInstance] authWithToken:token callback:^(ProximiioState result) {
/// if auth succeed
if (result == kProximiioReady) {
[[Proximiio sharedInstance] enable];
[[Proximiio sharedInstance] startUpdating];
[[Proximiio sharedInstance] setDelegate: self];
[[Proximiio sharedInstance] setBufferSize:kProximiioBufferMini];
[Proximiio sharedInstance].desiredAccuracy = kCLLocationAccuracyBestForNavigation;
}
}];
}
// Swift Example
import Proximiio
class MainViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let token = "APPLICATION_AUTH_TOKEN"
/// force request permission with background, use false if you don't need background
Proximiio.sharedInstance()?.requestPermissions(true)
/// show the main application
Proximiio.sharedInstance()?.auth(withToken: appToken, callback: { state in
/// if boot up of proximiio went fine
if state == kProximiioReady {
/// startup proximi.io
Proximiio.sharedInstance()?.enable()
Proximiio.sharedInstance()?.startUpdating()
/// set delegate
Proximiio.sharedInstance()?.delegate = self
}
}
}
}
// MARK: - Proximiio Delegate
extension MainViewController: ProximiioDelegate {
func onProximiioReady() {
}
func proximiioFloorChanged(_ floor: ProximiioFloor!) {}
func proximiioPositionUpdated(_ location: ProximiioLocation!) {
print(currentUserPosition)
}
}
You can get started with Proximi.io iOS SDK in less than 5 minutes! All you need is a Proximi.io account and obviously the SDK itself.
- Use CocoaPods (if you don't already have it installed, see the "Getting Started" guide) to easily install Proximi.io.
- Simply add
pod 'Proximiio'
in your Podfile. - And install the pod with the command
pod install
. open
.xcworkspace - Set
Enable Bitcode
toNO
in the project settings. - In order to use location and bluetooth services you need to add the following keys/value to your
Info.plist
<key>NSBluetoothAlwaysUsageDescription</key>
<string>Beacon to increase location position </string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>Allow bluetooth for improved beacon operation</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Allow Background Location updates for Event triggering while the App is in background</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>Allow always usage for permanent positioning support</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Allow location updates for basic Proximi.io SDK operation</string>
<key>NSMotionUsageDescription</key>
<string>Allow motion detection for improved positioning</string>
* If you are planning to use the SDK in background too please add this to <code>Info.plist</code>
```objc
<key>UIBackgroundModes</key>
<array>
<string>location</string>
</array>
- Include the Proximiio SDK
#include <Proximiio/Proximiio.h>
- Implement the
ProximiioDelegate
in a class of your choice and set that class as the delegate of the Proximiio SDK. - Authorize either via auth token and application name or via email and password.
Access
Proximi.io utilizes a singleton pattern to coordinate all functions and events. It simplifies access from anywhere in your code to the Proximi.io functions.
To get a pointer to the singleton, simply call:
/// Obj-C Example
#import <Proximiio/Proximiio.h>
ProximiioManager *proximiio = (ProximiioManager *)[Proximiio sharedInstance];
// Swift Example
import
let proximiio = Proximiio.sharedInstance()
Authentication
Proximi.io allows you to authenticate in two ways - via an auth token and an application name or by using your email and password. Both methods allow you to later change the application freely.
Authentitication only needs to be done once before using the API.
To authorize with your authentication token:
/// Obj-C Example
[[Proximiio sharedInstance] authWithToken:YOUR_AUTH_TOKEN];
// Swift Example
Proximiio.sharedInstance()?.auth(withToken: appToken, callback: { state in }
Positioning Engine Control
You can manually trigger proximi.io sdk positionining engine by calling
/// Obj-C Example
[[Proximiio sharedInstance] enable]
and
/// Obj-C Example
[[Proximiio sharedInstance] disable]
This will keep proximi.io instance in background and authorized, but it will not perform any location source updates, therefor is usefull in situation when constant position updates are not necessary and leads to more optimal battery usage.
Resetting the API (GDPR Compliance)
In order to meet GDPR compliance, you can reset the API and generate a new user (visitor) by calling the following function. It will reset all buffered positions and floor changes, so all events will be triggered again as the device is treated like new.
/// Obj-C Example
[[Proximiio sharedInstance] resetAndRefresh];
Background mode
SDK support background mode positioning too, in order to use this, please proceed updating your Info.plist
file adding this key/value:
<key>UIBackgroundModes</key>
<array>
<string>location</string>
</array>
And then initialize the code using:
/// Obj-C Example
[[Proximiio sharedInstance] requestPermissions: YES];
/// using NO it will allow you to get position only on app in foreground
/// Swift Example
Proximiio.sharedInstance()?.requestPermissions(true)
Processors
The new SDK allows you to apply post processing operation in a queue mode over the position calculated by the hardware interfaces (e.g. gps, beacon).
In this way the value can be tweaked or improved to provide a better or more complete experience to the user.
We provide some ready built processors:
- PDR (Pedestrian Dead Reck) -
ProximiioPDRProcessor
- Position Snap -
ProximiioSnapProcessor
For further details please refer to Github repository.
In order to use these you have just to add an extra pod
to your Podfile
:
pod "ProximiioProcessor"
Then in order to use those is just enough enque the processor before the SDK enable
.
/// Obj-C Example
#import <Proximiio/ProximiioProcessor.h>
/// add just after
[[Proximiio sharedInstance] enable];
/// add snap pre-processor
ProximiioSnapProcessor *snap = [ProximiioSnapProcessor new];
snap.threshold = 5.0;
[[[Proximiio sharedInstance] locationManager] addProcessor: snap];
// Swift Example
import ProximiioProcessor
/// add just after
Proximiio.sharedInstance()?.enable()
/// add snap pre-processor
let snap = ProximiioSnapProcessor()
snap.threshold = 5.0
Proximiio.sharedInstance()?.locationManager.addProcessor(snap, avoidDuplicates: true)
Synchronization and caching
The new SDK introduce data syncronization and caching.
It works with incremental delta and supports amenities
, features
and all the data used by SDK.
In order to preload them you can add those few lines of code after the auth is successfull (swift) or onProximiioReady
delegate is invoked.
/// Obj-C Example
[[Proximiio sharedInstance] sync:^(BOOL completed) {
}];
// Swift Example
/// force sync all data
Proximiio.sharedInstance()?.sync({ _ in
})
Object Management
Proximi.io SDK provide you access to the objects connected to the appToken
provided in the auth function.
You can access objects in this way:
/// Obj-C Example
/// places
NSArray *places = [[Proximiio sharedInstance] places];
/// floors
NSArray *floors = [[Proximiio sharedInstance] floors];
/// departments
NSArray *departments = [[Proximiio sharedInstance] departments];
/// geofences
NSArray *places = [[Proximiio sharedInstance] geofences];
/// inputs
NSArray *inputs = [[Proximiio sharedInstance] inputs];
/// privacy zones
NSArray *privacy = [[Proximiio sharedInstance] privacyZones];
// Swift Example
/// places
let places = Proximiio.sharedInstance()?.places
/// floors
let floors = Proximiio.sharedInstance()?.floors
/// departments
let departments = Proximiio.sharedInstance()?.departments
/// geofences
let geofences = Proximiio.sharedInstance()?.geofences
/// inputs
let inputs = Proximiio.sharedInstance()?.inputs
/// privacy zones
let privacy = Proximiio.sharedInstance()?.privacyZones
If you are know the uuid of a single object you can use a dedicated helper to get it:
/// Obj-C Example
ProximiioPlace *place = [[Proximiio sharedInstance] getPlace: "XXXXXXXXXXX"];
/// swift
let place = Proximiio.sharedInstance()?.getPlace(uuid: "XXXXXXXXXXXX")
Inputs (General)
Information
While all inputs are saved within the same class ProximiioInput
, the managing system to add and update them differentiate between their types (iBeacon, Eddystone, Custom).
You can cast the object to obtain all the information using this classes: ProximiioIBeacon
, ProximiioEddystone
.
Object relations
Example of relations.
/// Obj-C Example
//To get the parent of a floor (a place) you can either call
ProximiioPlace *placeParent = (ProximiioPlace*)[floor parent];
//or use the convenient function
ProximiioPlace *placeConvenient = [floor place];
//Both will return the same!
The ProximiioResource
is the base class for the other objects like ProximiioPlace
, ProximiioFloor
, ProximiioDepartment
, ProximiioInput
and ProximiioGeofence
.
These objects are in a hierarchical relation to each other.
- On the top level are the
ProximiioPlace
objects. - On the second level are each place's children, the floors -
ProximiioFloor
objects. - On the third level are each floor's children, the departments -
ProximiioDepartment
objects. - On the last level are each department's children, the inputs and geofences -
ProximiioInput
andProximiioGeofence
objects.
You can either use the parent
function of the ProximiioResource
class, or use the convenience functions of each subclass to get the upper levels. See the example on the side.
Some objects are orphans, so you should always check for nil
values!
Models
SDK exposes several data structure that can be used interact with user.
One note, we you have to interact with dictionaries (e.g. metadata), you can access the metadata value for a specific key (e.g. keyOne
) in this way:
let value = place.metadata["keyOne"] as? String
In order to access the value you have always to cast to the proper format you are expecting.
Here the model structure you can access to:
ProximiioDepartment
It's the model that holds information about a department, the basic structure provides:
- placeId (String)
- place (ProximiioPlace)
- floorId (String)
- floor (ProximiioFloor)
- name (String)
- tags (Array)
- metadata (Dictionary)
ProximiioFloor
It's the model that holds information about a floor, the basic structure provides:
- floorId (String)
- floorPlanImageURL (String)
- floorNumber (NSNumber)
- level (NSNumber)
- placeId (String)
- place (ProximiioPlace)
- name (String)
- anchors (Array of coordinates)
- metadata (Dictionary)
ProximiioGeofence / ProximiioPrivacyZone
It's the model that holds information about a geofence (or a privacy zone), the basic structure provides:
- name (String)
- type (String - Polygon or Circular)
- area (ProximiioLocation)
- address (String)
- radius (Double)
- polygon (Array of coordinates, empty if cirular)
- department (ProximiioDepartment)
- place (ProximiioPlace)
- floor (ProximiioFloor)
- metadata (Dictionary)
ProximiioInput
It's the model that holds information about an input, the basic structure provides:
- getMajor (Int)
- getMinor (Int)
- level (Int)
- type (ProximiioInputType / iBeacon or Eddystone)
- triggerFloorChange
- triggerVenueChange
- beaconUUID (UUID)
- namespaceId (String) - Only for Eddystone
- instanceId (String) - Only for Eddystone
- beaconData (Dictionary)
- department (ProximiioDepartment)
- location (ProximiioLocation)
- height - (Int)
- fixPosition - (Bool)
- fixPositionRange - (Double)
- fixLevel - (Bool)
- fixLevelRange - (Double)
ProximiioPlace
It's the model that holds information about a place, the basic structure provides:
- name (String)
- address (String)
- tags (Array)
- location (ProximiioLocation)
- metadata (Dictionary)
Delegate
The delegate ProximiioDelegate
of the Proximi.io base class plays a huge role in the use of the SDK.
Geofence
An event will be send when the user entered or exited a defined ProximiioGeofence
.
/// Objective-C
- (void)proximiioEnteredGeofence:(ProximiioGeofence*)geofence;
- (void)proximiioExitedGeofence:(ProximiioGeofence*)geofence;
/// Swift
func proximiioEnteredGeofence(_ geofence: ProximiioGeofence!) {
// notification on entering a geofence
}
func proximiioExitedGeofence(_ geofence: ProximiioGeofence!) {
// notificaion on exit a geofence
}
Position
An event will be send whenever the user position is updated through an input.
/// Objective-C
- (void)proximiioPositionUpdated:(CLLocation*)location;
/// Swift
func proximiioPositionUpdated(_ location: ProximiioLocation!) {}
iBeacon
An event will be send when an iBeacon is found, updated or lost.
/// Objective-C
- (void)proximiioFoundiBeacon:(ProximiioBeacon*)beacon isRegistered:(BOOL)registered;
- (void)proximiioUpdatediBeacon:(ProximiioBeacon*)beacon isRegistered:(BOOL)registered;
- (void)proximiioLostiBeacon:(ProximiioBeacon*)beacon isRegistered:(BOOL)registered;
/// Swift
func proximiioFoundiBeacon(_ beacon: ProximiioIBeacon!) {}
func proximiioUpdatediBeacon(_ beacon: ProximiioIBeacon!) {}
func proximiioLostiBeacon(_ beacon: ProximiioIBeacon!) {}
Eddystone
An event will be send when an Eddystone Beacon is found, updated or lost.
/// Objective-C
- (void)proximiioFoundEddystoneBeacon:(ProximiioEddystoneBeacon*)beacon isRegistered:(BOOL)registered;
- (void)proximiioUpdatedEddystoneBeacon:(ProximiioEddystoneBeacon*)beacon isRegistered:(BOOL)registered;
- (void)proximiioLostEddystoneBeacon:(ProximiioEddystoneBeacon*)beacon isRegistered:(BOOL)registered;
/// Swift
func proximiioFound(_ beacon: ProximiioEddystoneBeacon!) {}
func proximiioUpdatedEddystoneBeacon(_ beacon: ProximiioEddystoneBeacon!) {}
func proximiioLostEddystoneBeacon(_ beacon: ProximiioEddystoneBeacon!) {}
Management
An event will be send when a network object is created, updated or deleted.
/// Objective-C
- (void)proximiioUpdatedApplications;
- (void)proximiioUpdatedPlaces;
- (void)proximiioUpdatedFloors;
- (void)proximiioUpdatedDepartments;
- (void)proximiioUpdatedInputs;
- (void)proximiioUpdatedGeofences;
/// Swift
func proximiioUpdatedApplications() {}
func proximiioUpdatedPlaces() {}
func proximiioUpdatedFloors() {}
func proximiioUpdatedDepartments() {}
func proximiioUpdatedInputs() {}
func proximiioUpdatedGeofences() {}
AppStore Submission
The SDK architectures for Simulator need to be removed before submitting your app. Go to your Project Settings => Build Phases and click the + located on top left part of the window to Add Run Script Phase.
paste following code into script body of the created Run Script Phase
APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}"
# This script loops through the frameworks embedded in the application and
# removes unused architectures.
find "$APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORK
do
FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)
FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"
EXTRACTED_ARCHS=()
for ARCH in $ARCHS
do
echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME"
lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"
EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")
done
echo "Merging extracted architectures: ${ARCHS}"
lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}"
rm "${EXTRACTED_ARCHS[@]}"
echo "Replacing original executable with thinned version"
rm "$FRAMEWORK_EXECUTABLE_PATH"
mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"
done
Make sure the created Run Script Phase is located below "Embed Frameworks" Phase.
Troubleshooting
If the library produce error on build, try add these few lines at the bottom of your Podfile
.
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['SWIFT_VERSION'] = '5.2'
config.build_settings['ENABLE_BITCODE'] = 'NO'
end
end
end
Extras
Scan Triggering
/// Obj-C Example
[[Proximiio sharedInstance] startUpdating];
[[Proximiio sharedInstance] stopUpdating];
// Swift Example
Proximiio.sharedInstance()?.startUpdating()
Proximiio.sharedInstance()?.stopUpdating()
You can turn Proximii.io locationing on/off by using these methods.
iBeacon
/// Obj-C Example
[[Proximiio sharedInstance] addCustomiBeaconUUID:@"F7826DA6-4FA2-4E98-8024-BC5B71E0893E"];
You can add custom UUIDs that will be scanned for to the internal Proximi.io beacon scanner. This way the standard beacon delegate can be utilized further.
- (void) addCustomiBeaconUUID:(NSString*)uuid;