iOS SDK

This section shows you how to include datalinker in an existing iOS app. We assume that you have setup a SENDER service called com.myorg.sender and a document type called com.myorg.my-document-type.

AD_HOC and RECEIVER_INITIATED_RECEIVER services can be configured by user by scanning a QR code. This QR code contains the session ID to send the data to as well as an AES key and an initialization vector (in case of AD_HOC services) and a fingerprint (in case of RECEIVER_INITIATED_RECEIVER services). The datalinker UI handles the scanning of the QR code and the encryption for you. Refer to the Overview to implement this behavior yourself.

Note

The following guide assumes basic knowledge of CocoaPods for dependency management.

The datalinker iOS SDK is split into three pods.

  • Datalinker/Datalinker: This is the core pod for sending data.
  • Datalinker/DatalinkerUI: This pod contains the datalinker UI for the users of your app.
  • Datalinker/DatalinkerAnalytics: This pod simplifies the use of datalinker analytics to track user behavior.

Setting up CocoaPods

  1. Create a new Podfile for your project, if you don’t have one yet.

  2. Add the following dependencies:

    • pod 'Datalinker/Datalinker'
    • pod 'Datalinker/DatalinkerUI'
    • pod 'Datalinker/DatalinkerAnalytics'

    The first dependency is not necessary as it is required by the second and the third pod.

  3. Install the new pods and open your project.

Register your app as a client for your service

The current version of the iOS SDK is written in Objective-C. You can import it by adding a bridging header to your SwiftProject:

#import <Datalinker/Datalinker.h>
#import <DatalinkerUI/DatalinkerUI.h>
#import <DatalinkerAnalytics/DatalinkerAnalytics.h>

In your AppDelegate.swift file, add the following statement to configure your app to use datalinker:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    Datalinker.configureService("com.myorg.sender")
    }

This sets up your project to connect to your SENDER service. Each instance of your app will then create a new client of this service using an auto-generated password.

Adding receiver services

RECEIVER_INITIATED_RECEIVER services can be added either through the datalinker UI or programmatically. SENDER_INITIATED_RECEIVERS can only be added programatically.

Note

Use either the datalinker UI or a custom UI to add RECEIVER_INITIATED_RECEIVER services. It is not allowed to mix both ways in the same app.

Note

When adding SENDER_INITIATED_RECEIVERS, they will still be visible in the datalinker UI. However, they can only be paused and not be removed by the user. Don’t try to remove them in your code but instead deactivate them.

To add a receiver service, simply pass the service ID and a flag, to indicate if the service should be enabled by default:

Datalinker.addService("com.myorg.receiver-initiated", isEnabledByDefault: true)

Both receiver types can either be active or inactive. Data will only be sent to active services.

Using the datalinker UI

The datalinker UI makes managing services for your users a breeze. You can show it by specifying a presenting view controller.

if Datalinker.isReady() {
    Datalinker.presentShareView(self)
}

Note

Use the isReady() method to ensure that datalinker has finished configuring itself. If you show the UI before datalinker has logged your user in, it will not show the available services.

Sending data

Once you configured some services, you can send new data to all of them:

var data = [String: Any]()
data["timestamp"] = NSNumber(value: Date().timeIntervalSince1970)
data["number"] = NSNumber(value: (arc4random() % 9000 + 100))
Datalinker.sendData(data, withDocumentType: "com.myorg.my-document-type")

To send data only to a specific service, you can pass the receiver service as an argument:

var data = [String: Any]()
data["timestamp"] = NSNumber(value: Date().timeIntervalSince1970)
data["number"] = NSNumber(value: (arc4random() % 9000 + 100))
Datalinker.sendData(data, withDocumentType: "com.myorg.my-document-type", toService: "com.myorg.receiver-service")

Both methods work with both RECEIVER_INITIATED_RECEIVER and SENDER_INITIATED_RECEIVER services.

Optionally, you can add unencrypted parameters to you data:

var data = [String: Any]()
data["timestamp"] = NSNumber(value: Date().timeIntervalSince1970)
data["number"] = NSNumber(value: (arc4random() % 9000 + 100))

    var parameters = [String: Any]()
    parameters["foo"] = "bar"

    Datalinker.sendData("com.myorg.my-document-type", withDocumentType: "com.myorg.my-document-type", withParameters: parameters)
    Datalinker.sendData("com.myorg.my-document-type", withDocumentType: "com.myorg.my-document-type", toService: "com.myorg.reciever-service", withParameters: parameters)

Note

datalinker will start sending data the next time your app launches. It will preserve the correct order of the data.

Using AD_HOC services

AD_HOC services receive data once. To support these kind of services, your app has to register as a datalinker datasource. When a user scans a QR code for an AD_HOC service, your app will be asked to provide the relevant data.

To register as a datasource for datalinker, implement a Swift class conforming to the DatalinkerDataSource protocol and set it as the datasource:

Datalinker.setDataSource(self)

The datasource will need to implement methods for returning the number of documents to send, the document type ID of these documents and the actual data for each of this documents. The following example returns three documents for displaying random values with their associated timestamp.

func numberOfDocuments(forService serviceId: String!) -> Int {
    return 3
}

func document(at index: Int, forService serviceId: String!) -> [Any]! {
    var result = [[Any]]()

    let events = fetchedResultsController.fetchedObjects!

    switch index {
    case 0:
        var leftAxix = [Any]()
        for event in events {
            leftAxix.append([Int(event.timestamp!.timeIntervalSince1970 * 1000), event.value!.intValue])
        }
        var rightAxix = [Any]()
        for event in events {
            rightAxix.append([Int(event.timestamp!.timeIntervalSince1970 * 1000), pow(event.value!.decimalValue, 2)])
        }

        result.append(leftAxix)
        result.append(rightAxix)
    case 1:
        var leftAxix = [Any]()
        for event in events {
            leftAxix.append([Int(event.timestamp!.timeIntervalSince1970 * 1000), event.value!.intValue])
        }
        var rightAxix = [Any]()
        for event in events {
            rightAxix.append([Int(event.timestamp!.timeIntervalSince1970 * 1000), pow(event.value!.decimalValue, 2)])
        }

        result.append(leftAxix)
        result.append(rightAxix)
    case 2:
        var i = 1;
        for event in events {
            result.append([i, Int(event.timestamp!.timeIntervalSince1970 * 1000), event.value!.intValue])
            i += 1
        }
    default:
        break
    }

    return result
}

func documentTypeIdForDocument(at index: Int, forService serviceId: String!) -> String! {
    switch index {
    case 0:
        return "com.myorg.random-number-bar-chart"
    case 1:
        return "com.myorg.random-number-line-chart"
    case 2:
        return "com.myorg.random-number-table"
    default:
        return ""
    }
}

Using datalinker analytics

datalinker analytics is a SENDER_INITIATED_SERVICE for collecting user behavior inside your app. While very simple, it will provide you with raw data to give you full control. Data sent to datalinker analytics will be decrypted on the server and thus may not contain any personal or sensitive data. In particular, it is not premitted to send any user-identifiable information to datalinker analytics.

To start a new session, e. g. after launching the app, call the startSession() after launching the app>

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    Datalinker.configureService("com.myorg.sender")
    DatalinkerAnalytics.startSession()
    }

To send data to datalinker analytics, simply call its sendEvent() function:

DatalinkerAnalytics.sendEvent("Added a new random number.")

Again, you may add some parameters to this data:

var parameters = [String: Any]()
parameters["foo"] = "bar"

DatalinkerAnalytics.sendEvent("Added a new random number.", withParameters: parameters)

Resetting datalinker

Attention

datalinker’s reset() function may not be used in production environments. It is simply used to reset all configuration during development.

The datalinker SDK stores the assigned client ID and the generated password in your user’s keychain. In addition, it stores the configuration of all services as well as the data to send in the file system. To reset all of this information during development, call the reset() function.

Datalinker.reset()