Installation

Attention

This details the installation guide for Document Scan SDK 5.7.0 and above. For previous versions, see Installing Older Versions.

Requirements

  • Xcode 11+

  • iOS 13+

Minimum Supported Devices

  • iPhone 7 and 7 Plus

  • iPad 9.7” 6th Gen

  • iPad 10.2” 7th Gen

  • iPad Pro 10.5” and iPad Pro 12.9”

Add the XCFramework

The Document Scan SDK is distributed as an XCFramework with support for iOS and any iOS Simulator. While document capture is not supported on a Simulator, this allows you to run and test the rest of your application without the need for a physical device.

First, move the provided CFDocumentScanSDK.xcframework into your project directory or a subdirectory. Next, add it to your application target:

add-dependency

Select Other, then Add Files…:

add-files

Navigate to where CFDocumentScanSDK.xcframework is stored, select it, and then click Open:

select-xcframework-in-finder

Make sure the framework is set to Embed & Sign:

embed-and-sign

Add License Key

The SDK will not run without a valid license key. This should be provisioned to you by AuthenticID. You can assign this key in one of two ways:

  • Add a key to your Info.plist

  • Set the key programmatically

Option 1: Info.plist Key

Add the following to your application’s Info.plist:

<key>DocumentScanLicenseKey</key>
<string>YOUR_LICENSE_KEY</string>

Option 2: Set Key Programmatically

You can assign your license key using a static method on DSCapture. This must be set before starting any capture sessions.

// Swift
DSCapture.setLicense(key: "Provided SDK License Key")
// Objective-C
[DSCapture setLicenseKey:@"Provided SDK License Key")

Configure Required Permissions

The end-user must grant permission to use the camera before beginning a document capture session. The SDK may also optionally collect user location data, which requires granted location permissions.

Note

Location permissions are not required for a document capture session. Only request device permissions as they are needed for your application.

Camera Permission

Requesting permission to the device camera requires that you set a usage description in the Info.plist:

<key>NSCameraUsageDescription</key>
<string>The camera is needed to scan documents.</string>

The description will be displayed to the user when your application first asks for access to the camera. If you support multiple languages, this description can be localized; for more information, see Apple’s offical documentation on Information Property Lists.

You can then request camera permissions from the end-user via AVFoundation:

if AVCaptureDevice.authorizationStatus(for: .video) == .authorized {
    // Already Authorized
}
else {
    AVCaptureDevice.requestAccess(for: .video) { granted in
        if granted == true {
            // User granted access. Let the app continue.
        }
        else {
            // User denied access. The SDK may not continue.
        }
    }
}

For more detailed documentation, refer to Requesting Authorization for Media Capture on iOS.

Location Permission (Optional)

Requesting access to the end-user’s geolocation requires you set one or two usage descriptions in your Info.plist, depending on which type of access is needed:

<key>NSLocationWhenInUseUsageDescription</key>
<string>Location data is used to increase document fidelity.</string>

<!--You must also add an NSLocationAlwaysAndWhenInUseUsageDescription if "always" permission is required-->

The description will be displayed to the user when your application first requests for each level of permissions. If you support multiple languages, this description can be localized; for more information, see Apple’s offical documentation on Information Property Lists.

You can then request location permissions from the end-user via CoreLocation:

import UIKit
import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate {

    let locationManager = CLLocationManager()

    override func viewDidLoad() {
        super.viewDidLoad()

        // Handle authorization changes
        locationManager.delegate = self

        // Get the current permission
        let status = CLLocationManager.authorizationStatus()

        handle(authorizationStatus: status)
    }

    private func handle(authorizationStatus: CLAuthorizationStatus) {
        switch authorizationStatus {
        case .notDetermined:
            // We have not yet requested permission
            locationManager.requestWhenInUseAuthorization()
            return
        case .authorizedAlways, .authorizedWhenInUse:
            // We already have permission and can proceed
            break
        default:
            // User has denied permission, or parental / MDM settings
            // disallow it. The SDK will still function.
        }
    }

    // MARK: - CLLocationManagerDelegate

    func locationManagerDidChangeAuthorization(
        _ manager: CLLocationManager)
    {
        let status = CLLocationManager.authorizationStatus()
        handle(authorizationStatus: status)
    }
}

For more detailed documentation, refer to Requesting Authorization for Location Services.

Installing Older Versions

Danger

The following instructions are only for older versions (5.3.0 and below). We highly suggest using the latest version of the SDK.

In version 5.3.0 of the Document Scan SDK and below, the SDK binary was distributed solely as a “Fat Framework,” which is industry slang for a framework executable that contains multiple, often competing architectures. For example, a single iOS framework might be packaged with both arm64 and x86_64 slices in order to support both iOS devices and the iOS Simulator on Intel-based Mac’s. Traditionally, this was the standard way to distribute a single framework binary for multiple platforms. This does require extra work from implementing developers, details are included below.

Xcode 11 introduced a new packaging format to avoid this workaround: XCFramework. XCFrameworks contain multiple copies of a single framework, one for each set of platform architectures. Starting in version 5.3.1 of the Document Scan SDK, the new XCFramework packaging format is distributed.

First, move the provided CFDocumentScanSDK.framework into your project directory or a subdirectory. Next, add it to your application target:

add-dependency

Select Other, then Add Files…:

add-files

Navigate to where CFDocumentScanSDK.framework is stored, select it, and then click Open:

legacy-select-framework-in-finder

Make sure the framework is set to Do Not Embed. Since the framework contains ARM and Intel architectures, distribution build validation will fail if the framework is embedded in the application bundle. You will need to embed using a custom Run Script, covered in the next step:

legacy-embed-and-sign

On the Build Phases tab, add a new Run Script build phase:

legacy-add-run-script

Add the following to the Run Script body:

# Change this to NO to make equivalent to "Embed & Don't Sign"
SHOULD_CODE_SIGN=$CODE_SIGNING_ALLOWED

FRAMEWORKS_DIR=$BUILT_PRODUCTS_DIR"/"$PRODUCT_NAME".app/Frameworks"

embed_and_sign () {
    SOURCE_FRAMEWORK_PATH=$1
    # Embed framework in bundle
    cp -Rv "$SOURCE_FRAMEWORK_PATH" "$FRAMEWORKS_DIR"

    FRAMEWORK_NAME=$(basename $SOURCE_FRAMEWORK_PATH)

    TARGET_FRAMEWORK_PATH="$FRAMEWORKS_DIR/$FRAMEWORK_NAME"

    # Once embedded, we need to strip out unused architectures
    FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$TARGET_FRAMEWORK_PATH/Info.plist" CFBundleExecutable)
    FRAMEWORK_EXECUTABLE_PATH="$TARGET_FRAMEWORK_PATH/$FRAMEWORK_EXECUTABLE_NAME"

    unset EXTRACTED_ARCHS
    for ARCH in $ARCHS; do
        echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME"
        lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"
        EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")
    done

    echo "Merging extracted architectures: ${ARCHS}"
    lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}"
    rm "${EXTRACTED_ARCHS[@]}"

    mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"

    # Lastly, codesign if necessary
    if [[ $SHOULD_CODE_SIGN == "NO" ]]; then
        return
    fi

    # Code signing identity is provided based on Xcode build settings. If not provided, then we fall back to the classic CODE_SIGN_IDENTITY
    TARGET_IDENTITY="${EXPANDED_CODE_SIGN_IDENTITY_NAME}"

    if [[ "${TARGET_IDENTITY}" == "" ]]; then
        TARGET_IDENTITY="${CODE_SIGN_IDENTITY}"
        fi

    codesign --force --verbose --sign "${TARGET_IDENTITY}" "$TARGET_FRAMEWORK_PATH"
}

mkdir -p "$FRAMEWORKS_DIR"

INPUT_FILE_IDX=0

while [[ $INPUT_FILE_IDX -lt ${SCRIPT_INPUT_FILE_COUNT} ]]; do
    FILE_VARNAME="SCRIPT_INPUT_FILE_${INPUT_FILE_IDX}"
    FILE=${!FILE_VARNAME}

    echo "Embedding: $FILE"
    embed_and_sign "$FILE"

    let INPUT_FILE_IDX=$INPUT_FILE_IDX+1
done

Add the location of your CFDocumentScanSDK.framework as an Input File:

legacy-add-input-file