# Quick Start

{% hint style="info" %}
Check our public [sample application](https://github.com/dolphin-technologies/MOVE-sample-iOS) for an actual implementation of the snippets below and how they can be utilized.&#x20;
{% endhint %}

## Overall Code

A quick start snippet will look something like this in your app's [`willFinishLaunchWithOptions`](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623032-application):

```swift
import DolphinMoveSDK
#if canImport(DolphinMoveSDKHealth)
import DolphinMoveSDKHealth
#endif

func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
#if canImport(DolphinMoveSDKHealth)
		sdk.enable(healthKit: MoveSDKHealth.shared)
#endif
    MoveSDK.shared.setSDKStateListener { sdkState in
            switch state {
            case .uninitialized:
                print("/* SDK uninitialized*/")
                break
            case .ready:
                print("/* SDK initialised and ready to start the service*/")
                break
            case .running:
                print("/* SDK Started Detection*/")
                break
            }
    }
    
    MoveSDK.shared.setAuthStateUpdateListener { authState in  ... }    
    MoveSDK.shared.setTripStateListener       { tripState in ... }
    MoveSDK.shared.setServiceFailureListener  { failures in ... }
    MoveSDK.shared.setServiceWarningListener  { warnings in ... }

    MoveSDK.shared.initialize(launchOptions: launchOptions)
}
```

{% hint style="warning" %}
This snippet assumes that the required configurations and permissions are already setup to work. Check the [permissions handling](/move-platform/sdk/appendix/ios/permission-handling.md#required-permissions) section for more details.
{% endhint %}

### SDK Authorization and Setup

Users will need to be authenticated. This authentication will persist until shutdown is called. It will persist over the termination of the app. The configuration to enable functionality is passed here. `startAutomaticDetection` will start the services. This too will persist and services will automatically start when launching the app from the background.

{% hint style="info" %}
The authentication object is constructed with tokens that need to be acquired from the backend (either from the SDK backend directly, or via your product backend). See [MOVE Backend](/move-platform/backend/move-backend/move-admin-api.md#gettingstartedwiththedolphinmovetimelineservice-authentication).
{% endhint %}

```swift
import DolphinMoveSDK

// Response from the API Request.
// {
//  "authCode": "string"
// }

let authCode = ...

let sdkConfig = MoveConfig(
                detectionService: [
                .driving([.drivingBehavior, .distractionFreeDriving, .deviceDiscovery]),
                .walking([.location]), .cycling, .places,
                .publicTransport,
                .pointsOfInterest,
                .assistanceCall,
                .automaticImpactDetection
])

MoveSDK.shared.setup(authCode: authCode, config: config) { status in
    ...
}

...

MoveSDK.shared.startAutomaticDetection()
...
```

### Authentication Invalidation

{% hint style="warning" %}
The host app is expected to monitor [MoveAuthState](/move-platform/sdk/models/moveauthstate.md) updates via`authStateChangeListener`([iOS](/move-platform/sdk/api-interface/ios/services.md#set-sdk-auth-state-listener)) API and handle those changes accordingly.

Check [Authentication updates and expiry](/move-platform/sdk/models/moveauthstate.md#authentication-updates-and-expiry) for more details about authentication expiry and renewal.
{% endhint %}

An auth state listener must be implemented to handle user invalidation, which can happen due to a user being blocked or having multiple conflicting installations with the same user.

```swift
import DolphinMoveSDK

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

    ...

    MoveSDK.shared.setAuthStateUpdateListener { state in
        switch state {
        case .invalid:
            MoveSDK.shared.shutdown()
        }
    }

    MoveSDK.shared.initialize(launchOptions: launchOptions)

...
```

### SDK State

The host app is expected to set its [`SDKStateListener`](/move-platform/sdk/api-interface/ios/services.md#set-sdk-state-listener) **before** initializing the SDK to intercept the [MoveSDKState](/move-platform/sdk/models/movestate.md) changes.

The provided block could then start the SDK when [MoveSDKState](/move-platform/sdk/models/movestate.md) is `ready` or handle errors if occurred. The provided block could look something like this:&#x20;

```swift
MoveSDK.shared.setSDKStateListener { state in
    switch state {
    case .uninitialized:
        /* SDK uninitialized*/
        break
    case .ready:
        /* SDK initialised and ready to start the service*/
        break
    case .running:
        /* SDK Started Detection*/
        break
    }
}
```

### SDK Initialization&#x20;

{% hint style="warning" %}
The[`initialization`](/move-platform/sdk/api-interface/ios/intialization.md)API must be executed before[`didFinishLaunchingWithOptions`](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1622921-application)returns. We recommend calling it in[`willFinishLaunchingWithOptions`](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623032-application).\
\
Exceptions might apply, where the SDK is not initialized on app launch.  First initialization is a good example, where the app would only initialize the SDK after onboarding the user and requesting permissions. \
\
Check[ Initialization Timing](/move-platform/sdk/api-interface/ios/intialization.md#timing) for more details about the importance of adequately initializing the SDK.
{% endhint %}

```swift
MoveSDK.shared.initialize(launchOptions: launchOptions)
```

### Warnings and Errors

When services are not running properly because they are missing permissions or are not authorized on the backend, warnings or errors will be reported in the corresponding listeners.

```swift
MoveSDK.shared.setServiceFailureListener { failures in
    for failure in failures {
        /* a list of MoveServiceFailure objects */
        switch failure.reason {
	case .unauthorized:
	    /* a service is not configured on the backend */
	    break
	case let .missingPermission(permissions):
	    /* a required permission is missing */
	    break
        }
    }
}

MoveSDK.shared.setServiceWarningListener { warnings in
    for warning in warnings {
        /* a list of MoveServiceWarning objects */
        switch warning.reason {
	case let .missingPermission(permissions):
	    /* an optional permission is not provided, data collection will be reduced */
	    break
        }
    }
}
```

## WORKING SAMPLE CODE

```swift
import UIKit
import CoreMotion
import CoreLocation
import DolphinMoveSDK

@main
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {
    var locationManager = CLLocationManager()
    let activityManager = CMMotionActivityManager()
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        // ACQUIRE PERMISSIONS
        setupPermissions()
        
        // INITIALIZE MOVE SDK
        initializeSDK()
        
        return true
    }

    /// INITIALIZE MOVE SDK
    func initializeSDK(launchOptions: [UIApplication.LaunchOptionsKey: Any]?) {
        setupSDKListeners()

        MoveSDK.shared.initialize(launchOptions: launchOptions)
        if MoveSDK.shared.getSDKState() == .uninitialised {
            self.setupUser()
        }    
    }
    
    /// SETUP LISTENERS
    func setupSDKListeners() {
        MoveSDK.shared.setSDKStateListener { state in
            switch state {
            case .uninitialized:
                print("SDK uninitialized")
                break
            case .ready:
                print("SDK initialised and ready to start the service")
                break
            case .running:
                print("SDK Started Detection")
                break
            }
        }
        
        MoveSDK.shared.setServiceFailureListener { failures in
            for failure in failures {
                /* a list of MoveServiceFailure objects */
                switch failure.reason {
                case .unauthorized:
                    /* a service is not configured on the backend */
                    print("unauthorized")
                case let .missingPermission(permission):
                    /* a required permission is missing */
                    print(permission)
                    break
                }
            }
        }
        
        MoveSDK.shared.setServiceWarningListener { warnings in
            for warning in warnings {
                /* a list of MoveServiceWarning objects */
                switch warning.reason {
                case let .missingPermission(permissions):
                    /* an optional permission is not provided, data collection will be reduced */
                    print(permissions)
                    break
                }
            }
        }
    }
    
    /// ACQUIRE PERMISSIONS
    func setupPermissions() {
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.requestAlwaysAuthorization()
        locationManager.startUpdatingLocation()
        
        switch CMMotionActivityManager.authorizationStatus() {
        case .restricted, .denied:
            print("UNAUTHORIZED")
        case .authorized:
            print("AUTHORIZED")
        case .notDetermined:
            let activityManager = CMMotionActivityManager()
            activityManager.queryActivityStarting(from: Date(), to: Date(), to: .main) { (activity, error) in
            }
        }
    }
    
    /// SETUP USER
    func setupUser() {
        // API REQUEST - Post Request for Auth Code: 
        // Example: https://stackoverflow.com/a/26365148
        let authCode = ... 
               
        // SDK CONFIGURATION WITH SERVICES
        let sdkConfig = MoveConfig(
            detectionService: [
                .driving([.drivingBehavior, .distractionFreeDriving]),
                .walking([]), 
                .cycling, 
                .places,
                .publicTransport,
                .pointsOfInterest,
                .assistanceCall,
                .automaticImpactDetection
            ])

        // SETUP THE SDK WITH AUTH AND SDK CONFIG OBJECTS
        MoveSDK.shared.setup(authCode: authCode, config: sdkConfig) { status in
        }
        
        // START THE SDK SERVICES
        MoveSDK.shared.startAutomaticDetection()
    }
}

```

##


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.movesdk.com/move-platform/sdk/getting-started/ios/quick-start.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
