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:
Select Other, then Add Files…:
Navigate to where CFDocumentScanSDK.xcframework is stored, select it, and then click Open:
Make sure the framework is set to Embed & 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:
Select Other, then Add Files…:
Navigate to where CFDocumentScanSDK.framework is stored, select it, and then click Open:
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:
On the Build Phases tab, add a new Run Script build phase:
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: