iOS Migration Guide: RaxelPulse SDK to TelematicsSDK

This guide outlines the key changes between the deprecated RaxelPulse and the new TelematicsSDK. It provides a step-by-step comparison of deprecated methods and their replacements, along with migration instructions.

Adding the SDK to your project

Swift Package Manager

in Package.swift add the following:

dependencies: [
  .package(url: "https://github.com/Mobile-Telematics/telematicsSDK-iOS-new-SPM", from: "7.0.0")
],
targets: [
  .target(
    name: "MyProject",
    dependencies: [..., "TelematicsSDK"]
  )
  ...
]

It is necessary to update repo for new SPM from https://github.com/Mobile-Telematics/telematicsSDK-iOS-SPM to https://github.com/Mobile-Telematics/telematicsSDK-iOS-new-SPM

Install CocoaPods

Old methods
pod 'RaxelPulse
New methods
pod 'TelematicsSDK'

It is necessary to update pod from RaxelPulse to TelematicsSDK

SDK import

Old methods
import RaxelPulse
#import <RaxelPulse/RaxelPulse.h>
New methods
import TelematicsSDK
#import <TelematicsSDK/TelematicsSDK.h>

SDK Initialization

Old methods
RPEntry.initialize(withRequestingPermissions: false)
[RPEntry initializeWithRequestingPermissions:NO];
New methods
RPEntry.initializeSDK()
[RPEntry initializeSDK];

App delegate

Old methods
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
  let options = launchOptions ?? [:]
  RPEntry.application(application, didFinishLaunchingWithOptions: options)
  return true
}

func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
    RPEntry.application(application, handleEventsForBackgroundURLSession: identifier, completionHandler: completionHandler)
}

func applicationDidReceiveMemoryWarning(_ application: UIApplication) {
    RPEntry.applicationDidReceiveMemoryWarning(application)
}

func applicationWillTerminate(_ application: UIApplication) {
    RPEntry.applicationWillTerminate(application)
}

func applicationDidEnterBackground(_ application: UIApplication) {
    RPEntry.applicationDidEnterBackground(application)
}

func applicationWillEnterForeground(_ application: UIApplication) {
    RPEntry.applicationWillEnterForeground(application)
}

func applicationDidBecomeActive(_ application: UIApplication) {
    RPEntry.applicationDidBecomeActive(application)
}

func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    RPEntry.application(application) {
        completionHandler(.newData)
    }
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [RPEntry application:application didFinishLaunchingWithOptions:launchOptions];
}

- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(nonnull NSString *)identifier completionHandler:(nonnull void (^)(void))completionHandler {
    [RPEntry application:application handleEventsForBackgroundURLSession:identifier completionHandler:completionHandler];
}

- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
    [RPEntry applicationDidReceiveMemoryWarning:application];
}

- (void)applicationWillTerminate:(UIApplication *)application {
    [RPEntry applicationWillTerminate:application];
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
    [RPEntry applicationDidEnterBackground:application];
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
  [RPEntry applicationWillEnterForeground:application];
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
    [RPEntry applicationDidBecomeActive:application];
}

- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    [RPEntry application:application performFetchWithCompletionHandler:^{
        completionHandler(UIBackgroundFetchResultNewData);
    }];
}
New methods
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
  RPEntry.initializeSDK()
  RPEntry.instance.application(application, didFinishLaunchingWithOptions: launchOptions)
  return true
}

func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
    RPEntry.instance.application(application, handleEventsForBackgroundURLSession: identifier, completionHandler: completionHandler)
}

func applicationDidReceiveMemoryWarning(_ application: UIApplication) {
    RPEntry.instance.applicationDidReceiveMemoryWarning(application)
}

func applicationWillTerminate(_ application: UIApplication) {
    RPEntry.instance.applicationWillTerminate(application)
}

func applicationDidEnterBackground(_ application: UIApplication) {
    RPEntry.instance.applicationDidEnterBackground(application)
}

func applicationWillEnterForeground(_ application: UIApplication) {
    RPEntry.instance.applicationWillEnterForeground(application)
}

func applicationDidBecomeActive(_ application: UIApplication) {
    RPEntry.instance.applicationDidBecomeActive(application)
}

func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    RPEntry.instance.application(application) {
        completionHandler(.newData)
    }
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
	[RPEntry initializeSDK];
	[[RPEntry instance] application:application didFinishLaunchingWithOptions:launchOptions];
  return YES;
}

- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(nonnull NSString *)identifier completionHandler:(nonnull void (^)(void))completionHandler {
    [[RPEntry instance] application:application handleEventsForBackgroundURLSession:identifier completionHandler:completionHandler];
}

- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
    [[RPEntry instance] applicationDidReceiveMemoryWarning:application];
}

- (void)applicationWillTerminate:(UIApplication *)application {
    [[RPEntry instance] applicationWillTerminate:application];
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
    [[RPEntry instance] applicationDidEnterBackground:application];
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
  [[RPEntry instance] applicationWillEnterForeground:application];
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
    [[RPEntry instance] applicationDidBecomeActive:application];
}

- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    [[RPEntry instance] application:application performFetchWithCompletionHandler:^{
        completionHandler(UIBackgroundFetchResultNewData);
    }];
}

Important notifications

Low power mode

Old methods
class AppDelegate: RPLowPowerModeDelegate {
    RPEntry.instance().lowPowerModeDelegate = self
}

func lowPowerMode(_ state: Bool) {
        if (state) {
            self.showNotification(title: "Low Power Mode", body: "Your trips may be not recorded. Please, follow to Settings=>Battery=>Low Power")
        }
}

func showNotification(title: String, body: String) {
	let content = UNMutableNotificationContent()
        content.title = title
        content.subtitle = body
        content.sound = UNNotificationSound.default

        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)
        let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
        UNUserNotificationCenter.current().add(request)
}
@interface AppDelegate () <RPLowPowerModeDelegate> {
    [RPEntry instance].lowPowerModeDelegate = self;
}

- (void)lowPowerMode:(Boolean)state {
    if (state) {
        // You can create push in this place and fire about this, as example 
        
        UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
        content.title = @"Low Power Mode";
        content.body = [NSString stringWithFormat:@"Your trips may be not recorded. Please, follow to Settings=>Battery=>Low Power"];
        UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:1 repeats:NO];
        UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"overspeed" content:content trigger:trigger];

        [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:nil]; 
    }
}
New methods
class AppDelegate: RPLowPowerModeDelegate {
    RPEntry.instance.lowPowerModeDelegate = self
}

func lowPowerMode(_ state: Bool) {
        if (state) {
            self.showNotification(title: "Low Power Mode", body: "Your trips may be not recorded. Please, follow to Settings=>Battery=>Low Power")
        }
}

func showNotification(title: String, body: String) {
	let content = UNMutableNotificationContent()
        content.title = title
        content.subtitle = body
        content.sound = UNNotificationSound.default

        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)
        let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
        UNUserNotificationCenter.current().add(request)
}
@interface AppDelegate () <RPLowPowerModeDelegate> {
    [RPEntry instance].lowPowerModeDelegate = self;
}

- (void)lowPowerMode:(BOOL)state {
    if (state) {
        // You can create push in this place and fire about this, as example 
        
        UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
        content.title = @"Low Power Mode";
        content.body = [NSString stringWithFormat:@"Your trips may be not recorded. Please, follow to Settings=>Battery=>Low Power"];
        UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:1 repeats:NO];
        UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"overspeed" content:content trigger:trigger];

        [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:nil]; 
    }
}

Permissions wizard

Note that the SDK has a built-in Permissions Wizard and a Permissions Dialog that are fully customizable. To request user's permissions built-in Permissions Wizard can be used or you can implement your own logic to request Always Location permissions and Motion permissions

Old methods
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    RPPermissionsWizard.returnInstance().launch(finish: { _ in
        RPEntry.initialize(withRequestingPermissions: true)
        let token = NSString(string: "Please, enter your Token")
        RPEntry.instance().virtualDeviceToken = token
        let options = launchOptions ?? [:]
        RPEntry.application(application, didFinishLaunchingWithOptions: options)
    })
    return true
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [[RPPermissionsWizard returnInstance] launchWithFinish:^(BOOL showWizzard) {
        [RPEntry initializeWithRequestingPermissions:YES]; // Yes, if you don’t want to implement requesting by yourself
        [RPEntry instance].virtualDeviceToken = @"Please, enter your Token"
        [RPEntry instance].disableTracking = NO;
        [RPEntry application:application didFinishLaunchingWithOptions:launchOptions];
    }];
}
New methods
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
	RPEntry.initializeSDK()
	let options = launchOptions ?? [:]
    RPEntry.instance.application(application, didFinishLaunchingWithOptions: options)
    RPPermissionsWizard.returnInstance().launch(finish: { _ in
    	RPEntry.instance.virtualDeviceToken = "Please, enter your Token"
    	RPEntry.instance.disableTracking = false
    })
    return true
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
	[RPEntry initializeSDK];
	[[RPEntry instance] application:application didFinishLaunchingWithOptions:launchOptions];
    [[RPPermissionsWizard returnInstance] launchWithFinish:^(BOOL showWizzard) {
    	[RPEntry instance].virtualDeviceToken = @"Please, enter your Token"
        [RPEntry instance].disableTracking = NO;
    }];
}

Enable high-frequency data collection (HF)

Note: We strongly recommend keeping it enabled by default

Old methods
RPEntry.enableHF(true)
[RPEntry enableHF:true];
New methods

HF data is enabled by default.

Enable Accident detection.

Accident detection is disabled by default. You can enable detection.
In order for accident detection to work, you need to enable high-frequency data collection

Old methods
RPEntry.enableAccidents(true)
[RPEntry enableAccidents:true];
New methods
RPEntry.instance.enableAccidents(true)
[[RPEntry instance] enableAccidents:true];

Enable SDK.

Set a DeviceToken to SDK to enable it / SDK Log in.

Old methods
let token = NSString(string: "VIRTUAL_DEVICE_TOKEN") //REQUIRED!
RPEntry.instance().virtualDeviceToken = token
RPEntry.instance.setEnableSdk(true)
[RPEntry instance].virtualDeviceToken = @"VIRTUAL_DEVICE_TOKEN";
[[RPEntry instance] setEnableSdk:YES];
New methods
RPEntry.instance.virtualDeviceToken = "VIRTUAL_DEVICE_TOKEN"
RPEntry.instance.setEnableSdk(true)
[RPEntry instance].virtualDeviceToken = @"VIRTUAL_DEVICE_TOKEN";
[[RPEntry instance] setEnableSdk:YES];

Log out SDK

RPEntry.instance().removeVirtualDeviceToken()
[[RPEntry instance] removeVirtualDeviceToken];
New methods
RPEntry.instance.logout()
[[RPEntry instance] logout];

Update SDK to a specific version.

Old methods
pod 'RaxelPulse', '5.12'
New methods
pod 'TelematicsSDK', '7.0.0'

Methods for iOS app

SDK Initialization

First, initialize a new RPEntry class instance with a specified device ID. This method must be the first method calling from RaxelPulse SDK in the applicationdidFinishLaunchingWithOptions method.

Old methods
RPEntry.initialize(withRequestingPermissions: false)
[RPEntry initializeWithRequestingPermissions:NO];
New methods
RPEntry.initializeSDK()
[RPEntry initializeSDK];

Log in/Log out

if (userIsAuthenticated) {
    let token = NSString(string: "VIRTUAL_DEVICE_TOKEN") //REQUIRED!
    RPEntry.instance().virtualDeviceToken = token
    RPEntry.instance.setEnableSdk(true)
} else {
    /// empty device token is not allowed
    /// Use removeVirtualDeviceToken method for log out from the host app.
    RPEntry.instance().removeVirtualDeviceToken()
}
if ([self userIsAuthenticated]) {
    [RPEntry instance].virtualDeviceToken = [self getDeviceToken];
    [[RPEntry instance] setEnableSdk:YES];
} else {
    /// empty or nil  DeviceToken is not allowed
    /// Use removeVirtualDeviceToken method for log out from the host app.
    [[RPEntry instance] removeVirtualDeviceToken];
}
New methods
if (userIsAuthenticated) {
    RPEntry.instance().virtualDeviceToken = "VIRTUAL_DEVICE_TOKEN"
    RPEntry.instance.setEnableSdk(true)
} else {
    RPEntry.instance.logout()
}
if ([self userIsAuthenticated]) {
    [RPEntry instance].virtualDeviceToken = @"VIRTUAL_DEVICE_TOKEN";
    [[RPEntry instance] setEnableSdk:YES];
} else {
    [[RPEntry instance] logout];
}

Enable SDK.

Note: Empty or nil token is not allowed

Old methods
RPEntry.instance().setEnableSdk(true)
[[RPEntry instance] setEnableSdk:true];
New methods
RPEntry.instance.setEnableSdk(true)
[[RPEntry instance] setEnableSdk:true];

Disable SDK.

Old methods
RPEntry.instance().setEnableSdk(false)
[[RPEntry instance] setEnableSdk:false];
[[RPEntry instance] removeVirtualDeviceToken];
New methods

Note: It is not necessary to remove virtual device token. If sdk is disabled no any data will be collected.

RPEntry.instance.setEnableSdk(false)
[[RPEntry instance] setEnableSdk:false];

Disable SDK with enforced trip uploading

RPEntry.instance().setDisableWithUpload()
[[RPEntry instance] setDisableWithUpload];
New methods

Note: 'setDisableWithUpload' method is deprecated. Now 'setEnableSdk' method must be used.

RPEntry.instance.setEnableSdk(false)
[[RPEntry instance] setEnableSdk:false];

Check SDK status.

Old methods
let isSDKEnabled = RPEntry.isSDKEnabled()
BOOL isSDKEnabled = [RPEntry isSDKEnabled];
New methods
let isSDKEnabled = RPEntry.instance.isSDKEnabled()
BOOL isSDKEnabled = [[RPEntry instance] isSDKEnabled];

Check required permissions status.

Old methods
let isGranted = RPEntry.isAllRequiredPermissionsGranted()
BOOL isGranted = [RPEntry isAllRequiredPermissionsGranted];
New methods
let isGranted = RPEntry.instance.isAllRequiredPermissionsGranted()
BOOL isGranted = [[RPEntry instance] isAllRequiredPermissionsGranted];

Enable/ Disable Tracking.

Old methods
//Enable tracking
RPEntry.instance().disableTracking = false

//Disable tracking
RPEntry.instance().disableTracking = true
//Enable tracking
[RPEntry instance].disableTracking = NO;

//Disable tracking
[RPEntry instance].disableTracking = YES;
New methods
//Enable tracking
RPEntry.instance.disableTracking = false

//Disable tracking
RPEntry.instance.disableTracking = true
//Enable tracking
[RPEntry instance].disableTracking = NO;

//Disable tracking
[RPEntry instance].disableTracking = YES;

Manual start/ stop tracking.

Note: Manual start tracking doesn't disable automatic stop tracking.
Note: Persistent tracking ignores all stop tracking reasons and continues before 'stopTracking' method will be called. Max persistent tracking duration is 10 hours. then, it will be automatically terminated.

Old methods
//Manual start tracking
RPTracker.instance().startTracking()

//Manual stop tracking
RPTracker.instance().stopTracking()

//Manual start persistent tracking
RPTracker.instance().startPersistentTracking()
//Manual start tracking
[[RPTracker instance] startTracking];

//Manual stop tracking
[[RPTracker instance] stopTracking];

//Manual start persistent tracking
[[RPTracker instance] startPersistentTracking];
New methods
//Manual start tracking
RPEntry.instance.startTracking()

//Manual stop tracking
RPEntry.instance.stopTracking()

//Manual start persistent tracking
RPEntry.instance.startPersistentTracking()
//Manual start tracking
[[RPEntry instance] startTracking];

//Manual stop tracking
[[RPEntry instance] stopTracking];

//Manual start persistent tracking
[[RPEntry instance] startPersistentTracking];

Enable Aggressive Heartbeats.

The telematics SDK supports two operational modes for heartbeats;

Aggressive heartbeats - heartbeats are sent every 20 minutes. SDK is always active.
Normal Heartbeats - heartbeats are sent every 20 minutes but when SDK turns into Standby mode, it will be activated only by a new trip, and heartbeat will be sent respectively.

Note: Aggressive heartbeats significantly increases battery usage

Old methods
RPEntry.instance().setAggressiveHeartbeats(false)

//Check state
RPEntry.instance().aggressiveHeartbeat()
[[RPEntry instance] setAggressiveHeartbeats:NO];

//Check state
[[RPEntry instance] aggressiveHeartbeat];
New methods
RPEntry.instance.setAggressiveHeartbeats(false)

//Check state
RPEntry.instance.aggressiveHeartbeat()
[[RPEntry instance] setAggressiveHeartbeats:NO];

//Check state
[[RPEntry instance] aggressiveHeartbeat];

Enable high-frequency data collection (HF)

Note: We strongly recommend keeping it enabled by default

Old methods
RPEntry.enableHF(true)
[RPEntry enableHF:true];
New methods

HF data is enabled by default.

Enable Accident detection.

Accident detection is disabled by default. You can enable detection.
In order for accident detection to work, you need to enable high-frequency data collection

Old methods
RPEntry.enableAccidents(true)
[RPEntry enableAccidents:true];
New methods
RPEntry.instance.enableAccidents(true)
[[RPEntry instance] enableAccidents:true];

Enable Bluetooth OBD.

Bluetooth OBD/ELM functionality enables the host app to work with Bluetooth OBD devices to get in-vehicle data Dataset.

Note: Now RPELMEntry migrated from singleton to object of RPEntry and must be called: 'RPEntry.instance.elm'

Old methods
RPEntry.enableELM(true)
[RPEntry enableELM:YES];
New methods
RPEntry.instance.enableELM(true)
[[RPEntry instance] enableELM:YES];

Regular trip tags

Add trip tag.

Old methods
let tagExample = RPTag.init()
tagExample.tag = "BusinessTag"
tagExample.source = "TelematicsApp"
RPEntry.instance().api.addTrackTags([tagExample], to: "TRACK_TOKEN") { response, error in
    //
}
- (void)addTrackTags:(NSArray<RPTag *>*)tags to:(NSString *)trackToken completion:(id response, NSArray *error)callback;
New methods
let tagExample = RPTag(
    tag: "ExampleTag",
    source: "ExampleTagSource"
)

RPEntry.instance.api.addTrackTags([tagExample], to: "TRACK_TOKEN") { addedTags, error in
    if let error {
        print(error.localizedDescription)
        return
    }
            
    print(addedTags)
}
RPTag *tagExample = [[RPTag alloc] initWithTag:@"ExampleTag"
                                        source:@"ExampleTagSource"];

[[RPEntry instance].api addTrackTags:@[tagExample]
                                  to:@"TRACK_TOKEN"
                          completion:^(NSArray<RPTag *> * _Nonnull addedTags, NSError * _Nullable error) {
    if (error) {
        NSLog(@"%@", error.localizedDescription);
        return;
    }
    NSLog(@"%@", addedTags);
}];

Remove trip tag.

Old methods
let tagExample = RPTag.init()
tagExample.tag = "BusinessTag"
tagExample.source = "TelematicsApp"
RPEntry.instance().api.removeTrackTags([tagExample], from: "TRACK_TOKEN") { response, error in
    //
}
- (void)removeTrackTags:(NSArray<RPTag *>*)tags from:(NSString *)trackToken completion:(id response, NSArray *error)callback;
New methods
let tagExample = RPTag(
    tag: "ExampleTag",
    source: "ExampleTagSource"
)

RPEntry.instance.api.removeTrackTags([tagExample], from: "TRACK_TOKEN") { removedTags, error in
    if let error {
        print(error.localizedDescription)
        return
    }
            
    print(removedTags)
}
RPTag *tagExample = [[RPTag alloc] initWithTag:@"ExampleTag"
                                        source:@"ExampleTagSource"];

[[RPEntry instance].api removeTrackTags:@[tagExample]
                                   from:@"TRACK_TOKEN"
                             completion:^(NSArray<RPTag *> * _Nonnull removedTags, NSError * _Nullable error) {
    if (error) {
        NSLog(@"%@", error.localizedDescription);
        return;
    }
    NSLog(@"%@", removedTags);
}];

Get trip tags.

Old methods
RPEntry.instance().api.getTrackTags("TRACK_TOKEN") { response, error in
    //
}
- (void)getTrackTags:(NSString *)trackToken completion:(id response, NSArray *error)callback;
New methods
RPEntry.instance.api.getTrackTags("TRACK_TOKEN") { tags, error in
    if let error {
        print(error.localizedDescription)
        return
    }
            
    print(tags)
}
[[RPEntry instance].api getTrackTags:@"TRACK_TOKEN"
                          completion:^(NSArray<RPTag *> * _Nonnull tags, NSError * _Nullable error) {
    if (error) {
        NSLog(@"%@", error.localizedDescription);
        return;
    }
    NSLog(@"%@", tags);
}];

Period (Future) trip tags

Add a new tag.

Old methods
let tag = RPTag()
tag.tag = "ExampleTag"
tag.source = "ExampleTagSource"

RPEntry.instance().api.addFutureTrackTag(tag) { status, tag, timestamp in
    print(status)
    print(tag)
    print(timestamp)
    print("")
}
-(void)addFutureTrackTag:(RPTag *)tag completion:(RPAPIITagCallback)callback;
New methods
let tagExample = RPFutureTag(
    tag: "ExampleTag",
     source: "ExampleTagSource"
)
        
RPEntry.instance.api.addFutureTrackTag(tagExample) { status, error in
    if let error {
        print(error.localizedDescription)
        return
    }
            
    print(status.rawValue)
}
RPFutureTag *tagExample = [[RPFutureTag alloc] initWithTag:@"ExampleTag"
                                                    source:@"ExampleTagSource"];
    
[[RPEntry instance].api addFutureTrackTag:tagExample completion:^(enum RPTagStatus status, NSError * _Nullable error) {
    if (error) {
        NSLog(@"%@", error.localizedDescription);
        return;
    }
    NSLog(@"%ld", (long)status);
}];

Remove tag.

Old methods
let tag = RPTag()
tag.tag = "ExampleTag"
tag.source = "ExampleTagSource"

RPEntry.instance().api.removeFutureTrackTag(tag) { status, tag, timestamp in
    print(status)
    print(tag)
    print(timestamp)
}
-(void)removeFutureTrackTag:(RPTag *)tag completion:(RPAPIITagCallback)callback;
New methods
let tagExample = RPFutureTag(
    tag: "ExampleTag",
     source: "ExampleTagSource"
)
        
RPEntry.instance.api.removeFutureTrackTag(tagExample) { status, error in
    if let error {
        print(error.localizedDescription)
        return
    }
            
    print(status.rawValue)
}
RPFutureTag *tagExample = [[RPFutureTag alloc] initWithTag:@"ExampleTag"
                                                    source:@"ExampleTagSource"];
    
[[RPEntry instance].api removeFutureTrackTag:tagExample completion:^(enum RPTagStatus status, NSError * _Nullable error) {
    if (error) {
        NSLog(@"%@", error.localizedDescription);
        return;
    }
    NSLog(@"%ld", (long)status);
}];

Get tags.

Old methods
let timestamp = 0
RPEntry.instance().api.getFutureTrackTag(timestamp) { status, tags, timestamp in
    print(status)
    print(tags)
    print(timestamp)
}
-(void)getFutureTrackTag:(NSInteger)timestamp completion:(RPAPIITagGCallback)callback;
New methods
let dateExample = Date()
RPEntry.instance.api.getFutureTrackTag(dateExample) { status, tags in
    print(status.rawValue)
    print(tags)
}
NSDate *dateExample = [NSDate date];
[[RPEntry instance].api getFutureTrackTag:dateExample
                               completion:^(enum RPTagStatus status, NSArray<RPFutureTag *> * _Nonnull tags) {
    NSLog(@"%ld", (long)status);
    NSLog(@"%@", tags);
}];

Remove all tags.

Old methods
RPEntry.instance().api.removeAllFutureTrackTagsWithСompletion { status, timestamp in
    print(status.rawValue)
    print(timestamp)
}
-(void)removeAllFutureTrackTagsWithСompletion:(RPAPIITagWCallback)callback;
New methods
RPEntry.instance.api.removeAllFutureTrackTags { status, error in
    if let error {
        print(error)
        return
    }
    print(status.rawValue)
}
[[RPEntry instance].api removeAllFutureTrackTagsWithCompletion:^(enum RPTagStatus status, NSError * _Nullable error) {
    if (error) {
        NSLog(@"%@", error.localizedDescription);
        return;
    }
    NSLog(@"%ld", (long)status);
}];

Get a list of trips.

Old methods
func loadTracks() {
    RPEntry.instance().api.getTracks(0, limit: 100) { (response, error) in
        if let feed = response as? RPFeed {
            let tracks = feed.tracks;
            DispatchQueue.main.async {
                /// Implement updating your ViewController with new data
            }
        }
        if (error != nil) {
            DispatchQueue.main.async {
                /// Implement alert or logging
            }
        }
    }
}
- (void)loadTracks {
    [[RPEntry instance].api getTracksWithOffset:0 limit:10 completion:^(id response, NSError *error) {
        if (error != nil) {
            return;
        }
        
        if (![response isKindOfClass:[RPFeed class]]) {
            return;
        }
        
        RPFeed *feed = response;
        NSArray <RPTrackProcessed *> *tracks = feed.tracks;
 
        dispatch_async(dispatch_get_main_queue(), ^{ 
          // Implement updating your ViewController with new data            
        });
    }];
}
New methods
RPEntry.instance.api.getTracksWithOffset(0, limit: 10) { tracks, error in
    if let error {
        /// Implement updating your ViewController with error
        return
        }
        /// Implement updating your ViewController with new data
 }
[[RPEntry instance].api getTracksWithOffset:0
                                      limit:10
                                  startDate:nil
                                    endDate:nil
                                  ompletion:^(NSArray<RPTrackProcessed *> * _Nonnull tracks, NSError * _Nullable error) {
    if (error) {
        /// Implement updating your ViewController with error
        return;
    }
        /// Implement updating your ViewController with new data
    }];

Get trip details.

Old methods
RPEntry.instance().api.getTrackWithTrackToken("SELECTED_TRACK_TOKEN") { response, error in
    //
}
[[RPEntry instance].api getTrackWithTrackToken:@"SELECTED_TRACK_TOKEN" completion:^(id response, NSError *error) {
    RPTrackProcessed * track = response; // Detailed track information with points
}];
New methods
RPEntry.instance.api.getTrackWithTrackToken("SELECTED_TRACK_TOKEN") { track, error in
    if let error {
        /// Implement updating your ViewController with error
        return
    }
    if let track {
        /// Implement updating your ViewController with new data
    }
}
[[RPEntry instance].api getTrackWithTrackToken:@"SELECTED_TRACK_TOKEN"
                                    completion:^(RPTrackProcessed * _Nullable track, NSError * _Nullable error) {
    if (error) {
        /// Implement updating your ViewController with error
        return;
    }
    if (track) {
        /// Implement updating your ViewController with new data
    }
}];

Get trip origins.

New methods
RPEntry.instance.api.getTrackOrigins { trackOrigins, error in
    if let error {
        print(error.localizedDescription)
        return
    }
    guard let trackOrigins else { return }
            
    for trackOrigin in trackOrigins.trackOrigins {
        print(trackOrigin.trackOriginCode.rawValue)
        print(trackOrigin.displayName)
        print(trackOrigin.canBeSelected)
    }
}
[[RPEntry instance].api getTrackOriginsWithCompletion:^(RPTrackOrigins * _Nullable trackOrigins, NSError * _Nullable error) {
    if (error) {
        NSLog(@"%@", error.localizedDescription);
        return;
    }
        
    NSArray<RPTrackOrigin *> *origins = trackOrigins.trackOrigins;
    if (origins) {
        for (RPTrackOrigin * origin in origins) {
            NSLog(@"%ld", (long)origin.trackOriginCode);
            NSLog(@"%@", origin.displayName);
            NSLog(@"%d", origin.canBeSelected);
        }
    }
}];

Change a Transportation type.

Old methods
RPEntry.instance().api.changeTrackOrigin("USER_DRIVER_SIGNATURE_ROLE", forTrackToken: "SELECTED_TRACK_TOKEN") { response, error in
    
}
[[RPEntry instance].api changeTrackOrigin:'USER_DRIVER_SIGNATURE_ROLE' forTrackToken:'SELECTED_TRACK_TOKEN' completion:^(id response, NSError *error) {
    
}];
New methods
RPEntry.instance.api.changeTrackOrigin(.originalDriver, forTrackToken: "SELECTED_TRACK_TOKEN") { code, error in
            
}

//Avilable origins:
//.originalDriver
//.bus
//.motorcycle
//.other
//.passenger
//.running
//.taxi
//.train
//.walking
[[RPEntry instance].api changeTrackOrigin:RPTrackOriginCodeOriginalDriver
                            forTrackToken:@"SELECTED_TRACK_TOKEN'"
                               completion:^(RPStatusCodeResponse * _Nullable status, NSError * _Nullable error) {
        
}];

//Avilable origins:
//RPTrackOriginCodeOriginalDriver
//RPTrackOriginCodeBicycle
//RPTrackOriginCodeBus
//RPTrackOriginCodeMotorcycle
//RPTrackOriginCodeOther
//RPTrackOriginCodePassenger
//RPTrackOriginCodeRunning
//RPTrackOriginCodeTaxi
//RPTrackOriginCodeTrain
//RPTrackOriginCodeWalking

Upload unsent trips.

Old methods
RPEntry.instance().uploadUnsentTrips()
[[RPEntry instance] uploadUnsentTrips];
New methods
RPEntry.instance.uploadUnsentTrips()
[[RPEntry instance] uploadUnsentTrips];

Upload unsent trips.

Old methods
RPEntry.instance().getUnsentTripCount { count in
	print("unsent trips count - \(count)")
}
[[RPEntry instance] getUnsentTripCount:^(NSInteger count) {
    NSLog(@"unsent trips count - %ld", (long)count);
 }];
New methods
let count = RPEntry.instance.getUnsentTripCount()
print("unsent trips count - \(count)")
NSInteger count = [[RPEntry instance] getUnsentTripCount];
NSLog(@"unsent trips count - %ld", (long)count);

Send a custom heartbeat.

Old methods
RPEntry.instance().sendCustomHeartbeat("CustomHeartbeat") { success, error in
	if let error {
		print("error - \(error.localizedDescription)")
	}
}
[[RPEntry instance] sendCustomHeartbeat:@"CustomHeartbeat" completion:^(Boolean success, NSError * _Nullable error) {
    if (error) {
      NSLog(@"error - %@", error.localizedDescription);
    }
}];
New methods
RPEntry.instance.sendCustomHeartbeat("CustomHeartbeat") { success, error in
	if let error {
		print("error - \(error.localizedDescription)")
	}
}
[[RPEntry instance] sendCustomHeartbeat:@"CustomHeartbeat" completion:^(Boolean success, NSError * _Nullable error) {
    if (error) {
      NSLog(@"error - %@", error.localizedDescription);
    }
}];

Callbacks and Listeners

Tracking status.

Old methods
RPTracker.instance().isActive
[RPTracker instance].isActive
New methods
RPEntry.instance.isTrackingActive()
[[RPEntry instance] isTrackingActive];

Tracking status by notification.

Old methods
//Notification
NotificationCenter.default.addObserver(self,
                                       selector: #selector(self.observeTracker),
                                       name: .RPTrackerDidChangeActivity, 
                                       object: nil)

//Observe
@objc func observeTracker() {
	DispatchQueue.main.async {
  	let isActive = RPTracker.instance()?.isActive ?? false
    self.stateLabel.text = "Tracking = \(isActive)"
	}
}
//Notification
[[NSNotificationCenter defaultCenter]
     addObserver:self
     selector:@selector(observeTracker)
     name:RPTrackerDidChangeActivityNotification
     object:nil];

//Observe
- (void)observeTracker {
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        self.startButton.enabled = ![RPTracker instance].isActive;
        self.stopButton.enabled = [RPTracker instance].isActive;
        
        if ([RPTracker instance].isActive) {
            self.tokenLabel.text = @"tracking is active";
        } else {
            self.tokenLabel.text = @"tracking is not active";
        } 
    });
}
New methods
//Notification
NotificationCenter.default.addObserver(
            self,
            selector: #selector(observeTracker),
            name: NSNotification.RPTrackerDidChangeActivityNotification,
            object: nil
        )

//Observe
@objc func observeTracker() {
	DispatchQueue.main.async {
  	let isActive = RPEntry.instance.isTrackingActive()
    self.stateLabel.text = "Tracking = \(isActive)"
	}
}
//Notification
[[NSNotificationCenter defaultCenter]
     addObserver:self
     selector:@selector(observeTracker)
     name:NSNotification.RPTrackerDidChangeActivityNotification
     object:nil];

//Observe
- (void)observeTracker {
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    	BOOL isActive = RPEntry.instance.isTrackingActive()
        
        if (isActive) {
            self.stateLabel.text = @"tracking is active";
        } else {
            self.stateLabel.text = @"tracking is not active";
        } 
    });
}

Tracking status by delegate.

Old methods
class AppDelegate: UIResponder, UIApplicationDelegate, RPTrackingStateListenerDelegate {
    RPEntry.instance().trackingStateDelegate = self
}

//Delegate method
func trackingStateChanged(_ state: Bool) {
    var body = "Tracking Stoped"
    if state {
        body = "Tracking Started"
    }
    NSLog("tracking state changed to %@", body)
}
@interface AppDelegate () <RPTrackingStateListenerDelegate> {
    [RPEntry instance].trackingStateDelegate = self;
}

@end

//Delegate Method
- (void)trackingStateChanged:(Boolean)state {
    NSLog(@"tracking state changed to %hhu", state);
}
New methods
class AppDelegate: UIResponder, UIApplicationDelegate, RPTrackingStateListenerDelegate {
    RPEntry.instance.trackingStateDelegate = self
}

//Delegate method
func trackingStateChanged(_ state: Bool) {
    let body = state ? "Tracking Started" : "Tracking Stoped"
    print("tracking state changed to \(body)")
}
@interface AppDelegate () <RPTrackingStateListenerDelegate> {
    [RPEntry instance].trackingStateDelegate = self;
}

@end

//Delegate Method
- (void)trackingStateChanged:(BOOL)state {
    NSLog(@"tracking state changed to %hhu", state);
}

Location change and Events.

Old methods
class AppDelegate: UIResponder, UIApplicationDelegate, RPLocationDelegate {
    RPEntry.instance().locationDelegate = self
}

//Delegate Methods
func onLocationChanged(_ location: CLLocation!) {
    NSLog("location = %@", location)
}

func onNewEvents(_ events: NSMutableArray!) {
	for item in events {
  	if let theItem = item as? RPEventPoint {
    	NSLog("event id = %@ type = %@", theItem.theId, theItem.type)
    }
	}
}
@interface AppDelegate () <RPLocationDelegate> {
    [RPEntry instance].locationDelegate = self;
}

@end

//Delegate Methods
- (void)onLocationChanged:(CLLocation *)location {
    // Enter your code here to use location objectfrom SDK
}

- (void)onNewEvents:(NSMutableArray *)events {
    for (RPEventPoint *temp in events) {
        NSString *tempString = self.loggerView.text;
        tempString = [NSString stringWithFormat:@"%@\n%@", tempString, temp.type];
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.loggerView setText:tempString];
        });
    }
}
New methods
class AppDelegate: UIResponder, UIApplicationDelegate, RPLocationDelegate {
    RPEntry.instance.locationDelegate = self
}

//Delegate Methods
func onLocationChanged(_ location: CLLocation) {
    print("location = \(location)")
}

func onNewEvents(_ events: [RPEventPoint]) {
	for item in events {
    	print("event: \(event)")
    }
}
@interface AppDelegate () <RPLocationDelegate> {
    [RPEntry instance].locationDelegate = self;
}

@end

//Delegate Methods
- (void)onLocationChanged:(CLLocation * _Nonnull)location {
    // Enter your code here to use location object from SDK
}

- (void)onNewEvents:(NSArray<RPEventPoint *> * _Nonnull)events  {
    // Enter your code here to use event objects SDK
}

Low power mode.

Old methods
class AppDelegate: UIResponder, UIApplicationDelegate, RPLowPowerModeDelegate {
    RPEntry.instance().lowPowerModeDelegate = self
}

//Delegate Methods
func lowPowerMode(_ state: Bool) {
	if (state) {
  	self.showNotification(title: "Low Power Mode", body: "Your trips may be not recorded. Please, follow to Settings=>Battery=>Low Power")
  }
}
@interface AppDelegate () <RPLowPowerModeDelegate> {
    [RPEntry instance].lowPowerModeDelegate = self;
}
@end

//Delegate Methods
- (void)lowPowerMode:(Boolean)state {
    if (state) {
        // You can create push in this place and fire about this, as example 
        
        UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
        content.title = @"Low Power Mode";
        content.body = [NSString stringWithFormat:@"Your trips may be not recorded. Please, follow to Settings=>Battery=>Low Power"];
        UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:1 repeats:NO];
        UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"overspeed" content:content trigger:trigger];

        [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:nil]; 
    }
}
New methods
class AppDelegate: UIResponder, UIApplicationDelegate, RPLowPowerModeDelegate {
    RPEntry.instance.lowPowerModeDelegate = self
}

//Delegate Methods
func lowPowerMode(_ state: Bool) {
	if (state) {
  	self.showNotification(title: "Low Power Mode", body: "Your trips may be not recorded. Please, follow to Settings=>Battery=>Low Power")
  }
}
@interface AppDelegate () <RPLowPowerModeDelegate> {
    [RPEntry instance].lowPowerModeDelegate = self;
}
@end

//Delegate Methods
- (void)lowPowerMode:(BOOL)state {
    if (state) {
        // You can create push in this place and fire about this, as example 
        
        UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
        content.title = @"Low Power Mode";
        content.body = [NSString stringWithFormat:@"Your trips may be not recorded. Please, follow to Settings=>Battery=>Low Power"];
        UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:1 repeats:NO];
        UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"overspeed" content:content trigger:trigger];

        [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:nil]; 
    }
}

Low accuracy mode.

Old methods
class AppDelegate: UIResponder, UIApplicationDelegate, RPAccuracyAuthorizationDelegate {
    RPEntry.instance().accuracyAuthorizationDelegate = self
}

//Delegate Methods
func wrongAccuracyAuthorization() {
    let content = UNMutableNotificationContent()
    content.title = "Precise Location is off"
    content.subtitle = "Your trips may be not recorded. Please, follow to App Settings=>Location=>Precise Location"
    content.sound = UNNotificationSound.default
    // show this notification five seconds from now
    let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)
    // choose a random identifier
    let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
    // add our notification request
    UNUserNotificationCenter.current().add(request)
}
@interface AppDelegate () <RPAccuracyAuthorizationDelegate> {
    [RPEntry instance].accuracyAuthorizationDelegate = self;
}

//Delegate Methods
- (void)wrongAccuracyAuthorization {
    // You can create push in this place and fire about this, as example 
        
    UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
    content.title = @"Precise Location is off";
    content.body = [NSString stringWithFormat:@"Your trips may be not recorded. Please, follow to App Settings=>Location=>Precise Location"];
    UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:1 repeats:NO];
    UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"overspeed" content:content trigger:trigger];

    [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:nil];

}
New methods
class AppDelegate: UIResponder, UIApplicationDelegate, RPAccuracyAuthorizationDelegate {
    RPEntry.instance.accuracyAuthorizationDelegate = self
}

//Delegate Methods
func wrongAccuracyAuthorization() {
    let content = UNMutableNotificationContent()
    content.title = "Precise Location is off"
    content.subtitle = "Your trips may be not recorded. Please, follow to App Settings=>Location=>Precise Location"
    content.sound = UNNotificationSound.default
    // show this notification five seconds from now
    let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)
    // choose a random identifier
    let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
    // add our notification request
    UNUserNotificationCenter.current().add(request)
}
@interface AppDelegate () <RPAccuracyAuthorizationDelegate> {
    [RPEntry instance].accuracyAuthorizationDelegate = self;
}

//Delegate Methods
- (void)wrongAccuracyAuthorization {
    // You can create push in this place and fire about this, as example 
        
    UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
    content.title = @"Precise Location is off";
    content.body = [NSString stringWithFormat:@"Your trips may be not recorded. Please, follow to App Settings=>Location=>Precise Location"];
    UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:1 repeats:NO];
    UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"overspeed" content:content trigger:trigger];

    [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:nil];

}