iOS Quick Start#

Requirements#

The SafeRider SDK requires iOS 13 or higher. It is optimized for phones, not tablets. If these requirements are too limiting for you, contact us.

Installation#

CocoaPods#

The SafeRider SDK for iOS is available via CocoaPods and supports iOS 13 and higher versions. In your Podfile, just add these lines:

platform :ios, '13.0' # set the iOS min version of your app
...
pod 'SafeRider'
...
post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      # if the iOS min version of your app is higher than 13.0, add to your Podfile the commented code lines below
      #if target.name == 'Swinject' || target.name == 'DeviceKit'
      #  config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'
      #end
      ...
    end
  end
end

Then open a terminal and run this command:

pod install --repo-update

Swift Package Manager (SPM)#

We are not currently available through Swift Package Manager. Tell us if this is required for you.

Project Configuration#

You need to configure your XCode project as follows:

  • In your target settings, open the Signing & Capabilities tab

  • Locate the Background Modes section

  • Check the “Location updates” item

This is required to detect accidents when the screen is locked or the app is in the background.

Initialize the SDK#

You need to initialize the SDK by providing your API key.

You should only initialize the SafeRider SDK once, at the end of the app launching process.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]?) -> Bool {

    do {
        LRSafeRider.initialize(apiKey: "your_api_key", accidentUiScreenLogo: UIImage(named: "your_rectangular_logo")!)
    } catch {
        log.error("fail to init SafeRider: \(error.localizedDescription)")
    }

    return true
}

If you do not initialize it as explained above, you shall not be able to use it in your app.

Get the SDK instance#

You can get 2 different types of SDK instances, considering your programming habits or ways.

LRSafeRiderDelegationProtocol#

protocol LRSafeRiderDelegationProtocol: LRSafeRiderProtocol {

    var currentProtectionStatus: LRProtectionStatus { get }
    var protectionDelegate: LRProtectionDelegate? { get set }
    var protectionStartDelegate: LRProtectionStartDelegate? { get set }
    var problemReportDelegate: LRProblemReportDelegate? { get set }

    func startProtection(vehicleType: LRVehicleType, userId: String, phoneNumber: String, userFirstName: String?, userLastName: String?, metadata: [String : Any]?)
    func reportProblem()
}

You can get this protocol as explained below

var safeRiderInstance = LRSafeRider.getShared(LRSafeRiderDelegationProtocol.self)!

The delegation protocol comes with some delegates that help you to know what happens.

protocol LRProtectionDelegate {

    func onProtectionStatusChange(_ status: LRProtectionStatus)
    func onProtectionError(_ error: LRSaferiderError?)
    func onFallSurveyAnswer(_ fallSurveyAnswer: LRFallSurveyAnswer?)
}

The LRProtectionDelegate allows you to be notified of the changes of the protection status, the possible SDK errors or the possible user answer to the fall survey in case of accident alert.

protocol LRProtectionStartDelegate {

    func onProtectionStartSuccess()
    func onProtectionStartFailure(_ error: LRSaferiderError)
}

The LRProtectionStartDelegate allows you to be notified if your call to the function startProtection(...) of this protocol has succeeded or not (and the error if necessary)

protocol LRProblemReportDelegate {

    func onProblemReportSuccess()
    func onProblemReportFailure(_ error: LRSaferiderError)
}

The LRProblemReportDelegate allows you to be notified if your call to the function reportProblem() of this protocol has succeeded or not (and the error if necessary).

LRSafeRiderReactiveProtocol#

protocol LRSafeRiderReactiveProtocol: LRSafeRiderProtocol {

    var currentProtectionStatus: LRProtectionStatus { get }
    var protectionStatusPublisher: AnyPublisher<LRProtectionStatus, Never> { get }
    var protectionErrorPublisher: AnyPublisher<LRSaferiderError?, Never> { get }
    var fallSurveyAnswerPublisher: AnyPublisher<LRFallSurveyAnswer?, Never> { get }

    func startProtection(vehicleType: LRVehicleType, userId: String, phoneNumber: String, userFirstName: String?, userLastName: String?, metadata: [String : Any]?) -> AnyPublisher<Void, LRSaferiderError>
    func reportProblem() -> AnyPublisher<Void, LRSaferiderError>
}

You can get this protocol as explained below

var safeRiderInstance = LRSafeRider.getShared(LRSafeRiderReactiveProtocol.self)!

The reactive protocol provides basically the same services than the delegation one but exposing Combine publishers.

Start a Protection Session#

After initializing the SDK, you can start a protection session by calling startProtection(...). For details about each parameter, look at the iOS Reference.

This will start continuous processing to analyze sensor data and detect accidents. Only one session can be active on a device at a given time.

Before calling startProtection(...), you must ensure that user location updates could be received otherwise the SDK will return an error.

Using the LRSaferiderDelegationProtocol#

self.safeRiderInstance.protectionStartDelegate = self

self.safeRiderInstance.startProtection(vehicleType: .motorcycle, userId: "0000-0000-0000-0001", phoneNumber: "+33600000000", firstName: "John", lastName: "DOE", metadata: { "trip_id": "00000-000-0000-0001", "autostart": true })

extension MyClass: LRProtectionStartDelegate {

    func onProtectionStartSuccess() {
        log.info("succeed to start protection")
    }

    func onProtectionStartFailure(_ error: LRSaferiderError) {
        log.error("fail to start protection: \(error.localizedDescription)")
    }
}

Using the LRSaferiderReactiveProtocol#

var cancellableBag = Set<AnyCancellable>()

self.safeRiderInstance.startProtection(vehicleType: .motorcycle, userId: "0000-0000-0000-0001", phoneNumber: "+33600000000", firstName: "John", lastName: "DOE", metadata: { "trip_id": "00000-000-0000-0001", "autostart": true })
    .sink { completion in
        switch completion {
        case .failure(let error):
            log.error("fail to start protection: \(error.localizedDescription)")
        default: break
        }
     } receiveValue: { _ in
        log.info("succeed to start protection")
     }
     .store(in: &self.cancellableBag)

When you want to end the protection session, call stopProtection().

Listen to the SDK Protection Status change#

In order to be notified of the protection lifecycle, you have to listen to SDK status change events.

Using the LRSaferiderDelegationProtocol#

self.safeRiderInstance.protectionDelegate = self

extension MyClass: LRProtectionDelegate {

    func onProtectionStatusChange(_ status: LRProtectionStatus) {
        log.debug("new protection status: \(status)")
    }
}

Using the LRSaferiderReactiveProtocol#

var cancellableBag = Set<AnyCancellable>()

self.safeRiderInstance.protectionStatusPublisher
        .receive(on: DispatchQueue.main)
        .sink { status in
            log.debug("new protection status: \(status)")
        }
        .store(in: &self.cancellableBag)