Core

The Core framework provides convenient methods to the Validic API for uploading VLDRecord objects to Validic’s servers. It handles creating proper URLs, constructing the request object and parsing the server response. When not using [VLDSession submitRecord:] to upload data, it is recommended to use VLDAPIClient.

Requirements

The Validic Mobile library supports iOS 9 and above and requires Xcode version 8 or greater to compile.

Managing a Session

VLDSession stores a user, their current HealthKit subscriptions and all pending record uploads. This data is persisted between app launches but is deleted if endSession is called.

VLDSession is a singleton object and must be accessed by its sharedInstance method. The different frameworks of the Validic Mobile library rely on a valid user existing in the current VLDSession singleton object.

Starting a session

To start a VLDSession you will need a VLDUser object. A Validic user can be provisioned using the Validic API, documentation is available for both V1 and V2 Inform APIs. The credentials needed are a Validic user ID, an organization ID and a user access token.

let user = VLDUser(validicUserID:"user_id", organizationID:"organization_id", accessToken:"access_token")

The user object is then passed to the startSessionWithUser: method.

VLDSession.sharedInstance().start(with: user)

Best Practices

Check for an existing user in VLDSession before performing core logic related to your app.

guard let _ = VLDSession.sharedInstance().user else {
    showLoginScreen()
    return
}

Starting a session will delete the current session if it exists, clearing the cache user and any pending records that haven’t been uploaded.

Records

The Validic Mobile library supports the following record types:

  • VLDBiometrics - comprised of a user’s biometric health data such as blood pressure, body temperature, SpO2, cholesterol, heart rate, and blood and hormone levels.
  • VLDDiabetes - comprised of a user’s blood glucose and hormone levels related to diabetes treatment and management.
  • VLDFitness - comprised of a user’s activities that are undertaken with the express purpose of exercising. These activities have a defined duration (time, distance, elevation, etc.)
  • VLDNutrition - comprised of a user’s activities related to calorie intake and consumption and nutritional information (such as fat, protein, carbohydrates, sodium, etc.)
  • VLDRoutine - comprised of a user’s activities that occur regularly throughout the day, without the specific goal of exercise, for example calories burned and consumed, steps taken, stairs climbed. These activities are aggregate throughout the day. Also includes Apple Exercise Minutes and Mindful Minutes.
  • VLDSleep - comprised of a user’s measurements related to the length of time spent in various sleep cycles, as well as number of times woken during the night.
  • VLDWeight - comprised of a user’s weight and body mass.

More information about record types can be found here.

Record Submission Notifications

When VLDSession uploads a record it will send an NSNotification. To listen for this notification add an observer to the NSNotificationCenter with the constant kVLDRecordSubmittedNotification.

 NotificationCenter.default.addObserver(self, selector: #selector(recordDidUpload(_:)), name: NSNotification.Name.vldRecordSubmitted, object: nil)

When the notification is posted the object property of the notification will contain the VLDRecord object uploaded.

@objc func recordDidUpload(_ notification: Notification) {
    guard let record = notification.object as? VLDRecord else {
        return
    }
}

When VLDSession uploads an image it will send an NSNotification. To listen for this notification Add an observer to NSNotificationCenter with the constant kVLDRecordImageSubmittedNotification.

 NotificationCenter.default.addObserver(self, selector: #selector(imageDidUpload(_:)), name: NSNotification.Name.vldRecordImageSubmitted, object: nil)

The object property of the notification will contain a VLDMedia object containing an ID for the image, and its URL.

@objc func imageDidUpload(_ notification: Notification) {
    guard let record = notification.object as? VLDMedia else { return }
    print(record.mediaID ?? "")
    print(record.mediaURL ?? "")
}

If a 400 error is returned from the server, the record will be discarded and an NSNotification will be posted. To listen for this notification add an observer to the NSNotificationCenter with the constant kVLDRecordSubmissionFailedNotification.

 NotificationCenter.default.addObserver(self, selector: #selector(recordSubmissionDidFail(_:)), name: NSNotification.Name.vldRecordSubmissionFailed, object: nil)

The object property of the notification will contain the invalid VLDRecord object. The userInfo dictionary for this notification will contain one key, error with the NSError object for the failed upload.

@objc func recordSubmissionDidFail(_ notification: Notification) {
    guard let userInfo = notification.userInfo as? [String: Any],
        let error = userInfo["error"] as? NSError,
        let record = notification.object as? VLDRecord else {
            return
    }
    print("Record submission failed with error: \(error)")
    print("Record: \(record)")
}

If VLDSession attempts to upload the image associated with a record and the upload fails, an NSNotification, kVLDRecordImageSubmissionFailedNotification will be posted.

NotificationCenter.default.addObserver(self, selector: #selector(imageSubmissionDidFail(_:)), name: NSNotification.Name.vldRecordImageSubmissionFailed, object: nil)
@objc func imageSubmissionDidFail(_ notification: Notification) {
    guard let userInfo = notification.userInfo as? [String: Any],
        let error = userInfo["error"] as? NSError,
        let media = notification.object as? VLDMedia else {
            return
    }
    print("Record submission failed with error: \(error)")
    print("Media: \(media)")
}