Scan multipage documents with the iOS system camera
One.iOS.VNDocumentCameraViewController presents VisionKit’s document camera,
including its multipage capture, crop and review UI. It requires an iOS build,
a supported physical device and ios.infoPlist.NSCameraUsageDescription.
isSupported is the SDK capability check, not a camera permission grant.
Simulators cannot scan documents.
import { One } from 'one'
if (One.iOS.VNDocumentCameraViewController.isSupported) { const camera = new One.iOS.VNDocumentCameraViewController() camera.delegate = { documentCameraViewController: async (controller, result) => { try { if ('didFinishWith' in result) { const scan = result.didFinishWith for (let at = 0; at < scan.pageCount; at++) { const image = scan.imageOfPage(at) const bytes = image.pngData() // consume the encoded page bytes here. } } else { const error = result.didFailWith console.error(error.domain, error.code, error.localizedDescription) } } finally { await controller.dismiss() } }, documentCameraViewControllerDidCancel: (controller) => { void controller.dismiss() }, } await camera.present()}The delegate owns dismissal, as in VisionKit. Retain the controller while using it. Each controller has its own delegate and presentation state. A concurrent presentation on the same controller rejects; cancellation never fabricates a scan. Delegate errors preserve the native NSError domain, code and localized description. Presentation errors reject the promise before a delegate result.
| Class availability | Type | Description |
|---|---|---|
isSupportedbooleanStatic SDK device support check. False on web; native getter requires an iOS build. | boolean | Static SDK device support check. False on web; native getter requires an iOS build. |
| Controller | Type | Description |
|---|---|---|
delegateVNDocumentCameraViewControllerDelegate<VNDocumentCameraViewControllerInstance> | nullReceives completion, cancellation or failure. Defaults to null. | VNDocumentCameraViewControllerDelegate<VNDocumentCameraViewControllerInstance> | null | Receives completion, cancellation or failure. Defaults to null. |
present(animated?: boolean) => Promise<void>Presents from the current app controller. Resolves after presentation; animated defaults to true. | (animated?: boolean) => Promise<void> | Presents from the current app controller. Resolves after presentation; animated defaults to true. |
dismiss(animated?: boolean) => Promise<void>Dismisses the camera. Resolves after dismissal; animated defaults to true. | (animated?: boolean) => Promise<void> | Dismisses the camera. Resolves after dismissal; animated defaults to true. |
VNDocumentCameraViewControllerDelegate.documentCameraViewController(controller, result) receives { didFinishWith: scan } or { didFailWith: error }.
documentCameraViewControllerDidCancel(controller) receives cancellation.
These adapt Swift’s labeled delegate overloads to JavaScript. present and
dismiss adapt UIViewController presentation to the current app presenter;
the native camera content is unchanged.
VNDocumentCameraScan retains the native scan. title is a string, pageCount
is a number, and imageOfPage(at) returns the native page image. Indices must
be integers within 0..<pageCount. The returned UIImage subset exposes
size: { width, height } in points, scale, pngData() and
jpegData(compressionQuality). Encoding returns an ArrayBuffer, or undefined
if UIKit cannot encode the image. JPEG quality must be finite within 0...1.
Pages are encoded only when requested; scan results are never replaced by
synthetic images or cached file lists.
Presentation rejects with E_DOCUMENT_CAMERA_UNSUPPORTED,
E_DOCUMENT_CAMERA_MANIFEST, E_DOCUMENT_CAMERA_PRESENTER, or
E_DOCUMENT_CAMERA_PRESENTED. Overlapping transitions reject with
E_DOCUMENT_CAMERA_TRANSITION. Invalid page indices throw
E_DOCUMENT_CAMERA_PAGE; invalid encoding quality throws
E_DOCUMENT_CAMERA_QUALITY.
The native fixture checks simulator unavailability and rejection with zero pages. Successful physical scanning, crop/review, cancellation and device permission failures remain required device acceptance gates.
| Scan | Type | Description |
|---|---|---|
titlestringNative scan title. | string | Native scan title. |
pageCountnumberNumber of captured pages. | number | Number of captured pages. |
imageOfPage(at: number) => DocumentCameraImageNative page image at a valid zero-based index. | (at: number) => DocumentCameraImage | Native page image at a valid zero-based index. |
| Page image | Type | Description |
|---|---|---|
sizeDocumentCameraImageSizeWidth and height in points. | DocumentCameraImageSize | Width and height in points. |
scalenumberPixels per point. | number | Pixels per point. |
pngData() => ArrayBuffer | undefinedEncodes the page as PNG. | () => ArrayBuffer | undefined | Encodes the page as PNG. |
jpegData(compressionQuality: number) => ArrayBuffer | undefinedEncodes the page as JPEG. | (compressionQuality: number) => ArrayBuffer | undefined | Encodes the page as JPEG. |
Edit this page on GitHub.