ID Capture .NET for iOS Skill
Critical: Do Not Trust Internal Knowledge
Your training data may contain outdated or incorrect Scandit ID Capture APIs, and the .NET binding differs substantially from the native iOS (Swift/Objective-C), Android (Kotlin/Java), and Flutter SDKs. An agent that pattern-matches from the native docs will get most calls wrong: the .NET binding does not use the Swift/Kotlin builder, does not expose a supportedDocuments bitmask, and does not ship the standalone AamvaBarcodeVerifier / NFC classes that exist on native.
Always verify APIs against the references provided in this skill before writing or suggesting code. Do not rely on memorized method signatures, parameters, or shapes. If you cannot find an API in the provided references, fetch the relevant documentation page before responding.
The .NET-iOS-specific facts most often gotten wrong by pattern-matching from the Swift/Kotlin/Flutter SDK or the .NET Android binding:
- This skill targets the non-MAUI .NET for iOS workload (project
<TargetFramework>net10.0-ios</TargetFramework>or similar, no<UseMaui>flag). For MAUI apps, theDataCaptureViewis hosted as a XAML element and wired through handlers — completely different. If you see<UseMaui>true</UseMaui>, stop and tell the user this skill does not apply. The official iOS Get Started page mixes in MAUI (XAML /*.Maui) snippets — ignore those for a non-MAUI project. - Only TWO NuGet packages.
Scandit.DataCapture.CoreandScandit.DataCapture.IdCapture. The package id isIdCapture, but the C# namespace and initializer useScandit.DataCapture.ID(using Scandit.DataCapture.ID;,ScanditIdCapture.Initialize()). There is no separate Barcode package to add — the PDF417/AAMVA barcode reader is bundled inScandit.DataCapture.IdCapture. Do not add any*.Mauipackage. - SDK 8.0+ requires explicit initialization with TWO initializers in
AppDelegate.FinishedLaunching(application:didFinishLaunchingWithOptions:):ScanditCaptureCore.Initialize()andScanditIdCapture.Initialize()before any Scandit type is constructed. Missing the ID one crashes the firstIdCapture.Create(...)call. IdCaptureSettingsis configured with an object initializer / property sets — NOT a builder and NOT a bitmask. You setAcceptedDocuments(anIList<IIdCaptureDocument>) andScanner(anIdCaptureScanner). The Swift/Kotlin/oldsupportedDocuments+IdDocumentTypebitmask does not exist in .NET.- Documents are constructed with
new, taking anIdCaptureRegion:new Passport(IdCaptureRegion.Any),new DriverLicense(IdCaptureRegion.Us),new IdCard(IdCaptureRegion.Any),new ResidencePermit(...),new HealthInsuranceCard(...),new VisaIcao(...), andnew RegionSpecific(RegionSpecificSubtype.X).IdCaptureRegionvalues are C# PascalCase (Any,Us,EuAndSchengen, …), not the Swift/Kotlin style. - The scanner is a wrapper:
new IdCaptureScanner(physicalDocument: <IPhysicalDocumentScanner?>, mobileDocument: <MobileDocumentScanner?>). Physical =new FullDocumentScanner()(front+back, the default choice) ornew SingleSideScanner(barcode, machineReadableZone, visualInspectionZone). Mobile =new MobileDocumentScanner(iso180135, ocr). Assign it tosettings.Scanner. IdCaptureis created with a FACTORY, notnew:IdCapture.Create(dataCaptureContext, settings)(the constructor is private). There is also aCreate(settings)overload.- You manage the camera yourself, and
RecommendedCameraSettingsis applied to the camera (not passed toGetDefaultCamera):Camera.GetDefaultCamera(), thencamera.ApplySettingsAsync(IdCapture.RecommendedCameraSettings), thendataCaptureContext.SetFrameSourceAsync(camera), thencamera.SwitchToDesiredStateAsync(FrameSourceState.On/Off)across theUIViewControllerlifecycle.RecommendedCameraSettingsis a static property onIdCapture. iOS additionally offersFrameSourceState.Standby(a lighter pause that keeps the camera warm) versus.Off. DataCaptureView.Create(DataCaptureContext, CGRect frame)takes aCGRectas its second argument on iOS — typicallythis.View!.Bounds(orthis.View?.Frame ?? CGRect.Empty). This is the opposite of the .NET Android binding, whereDataCaptureView.Create(context)takes only the context. The returned view is aUIKit.UIView(implicit conversion), so you add it yourself withthis.View.AddSubview(dataCaptureView)and usually setAutoresizingMask = FlexibleWidth | FlexibleHeight. There is nocontainer.AddView(...)(that's Android).- The view is a generic
DataCaptureView; the overlay isIdCaptureOverlay.Create(idCapture, dataCaptureView)(a two-arg factory that auto-attaches). Then optionally setoverlay.IdLayoutStyle = IdLayoutStyle.Square(IdLayoutStylelives inScandit.DataCapture.ID.UI.Overlay). - Results come via
IIdCaptureListenerwith TWO callbacks:OnIdCaptured(IdCapture, CapturedId)andOnIdRejected(IdCapture, CapturedId?, RejectionReason). Both run on a background/arbitrary thread — dispatch UI work to the main thread withDispatchQueue.MainQueue.DispatchAsync(...)orUIApplication.SharedApplication.InvokeOnMainThread(...)(not Android'sRunOnUiThread), and setidCapture.Enabled = falsewhile a result dialog is shown, re-enabling it afterwards. A standalone listener implementation derives fromNSObject(aUIViewControlleralready is one, so it can implementIIdCaptureListenerdirectly). - Read field values via
CapturedId: top-levelFullName/FirstName/LastName(string?),DateOfBirth/DateOfExpiry/DateOfIssue(aDateResult?withDay/Month/Yearints plusUtcDate/LocalDate),DocumentNumber,Nationality,Sex(raw string) /SexType(Sexenum),Age,Address, and the document viaDocument?.DocumentType(IdCaptureDocumentType). The richer sub-results arecapturedId.Mrz/capturedId.Viz/capturedId.Barcode/capturedId.MobileDocument/capturedId.MobileDocumentOcr(note: properties areMrz/Viz/Barcode, notMrzResult/VizResult/BarcodeResult), pluscapturedId.ImagesandcapturedId.VerificationResult. - Verification is settings-driven on .NET — there is NO
AamvaBarcodeVerifier/DataConsistencyVerifierclass. Enable checks viaIdCaptureSettingsflags (RejectForgedAamvaBarcodes,RejectInconsistentData,RejectNotRealIdCompliant, …) and read the outcome fromcapturedId.VerificationResult(DataConsistency/AamvaBarcodeVerification). See references/advanced.md. - NFC chip reading and the deserializer API are NOT in the .NET surface. Do not reference
NfcScanner,NfcResult,CapturedId.Nfc, orIdCaptureDeserializer— they don't exist on .NET iOS. - Document images are
UIImage?(UIKit.UIImage) on iOS —capturedId.Images.Face,.Frame,.GetCroppedDocument(IdSide),.GetFrame(IdSide)andDataConsistencyResult.FrontReviewImageall returnUIImage?, not Android'sAndroid.Graphics.Bitmap?. - Camera permission is handled by iOS automatically via the
NSCameraUsageDescriptionkey inInfo.plist. The OS shows the permission prompt the first time the camera switches on. There is no runtime-permission helper class (that's the Android binding'sCameraPermissionActivity). IfNSCameraUsageDescriptionis missing, the app crashes when the camera starts. - iOS
SupportedOSPlatformVersionmust be ≥15.0in the.csproj(the Scandit iOS framework's minimum deployment target); the matchingMinimumOSVersiongoes inInfo.plist.
Forbidden APIs (commonly hallucinated — do NOT emit these)
These compile-fail against the real .NET packages. Use the right-hand form:
| Do NOT write | Use instead |
|---|---|
new IdCapture(...) / IdCapture.ForDataCaptureContext(...) |
IdCapture.Create(context, settings) |
IdCaptureSettings.builder() / settings.SupportedDocuments / IdDocumentType bitmask |
new IdCaptureSettings { AcceptedDocuments = [ … ], Scanner = … } |
settings.ScannerType = ... |
settings.Scanner = new IdCaptureScanner(physicalDocument: …, mobileDocument: …) |
IdCaptureOverlay.NewInstance(...) |
IdCaptureOverlay.Create(idCapture, dataCaptureView) |
DataCaptureView.Create(context) (no frame) |
DataCaptureView.Create(context, this.View!.Bounds) then this.View.AddSubview(view) |
RunOnUiThread(...) (Android) |
DispatchQueue.MainQueue.DispatchAsync(...) / UIApplication.SharedApplication.InvokeOnMainThread(...) |
capturedId.MrzResult / capturedId.VizResult / capturedId.BarcodeResult |
capturedId.Mrz / capturedId.Viz / capturedId.Barcode |
capturedId.IsPassport() / IsDriverLicense() / IsIdCard() |
capturedId.Document?.DocumentType (IdCaptureDocumentType) or capturedId.IsRegionSpecific(subtype) |
new AamvaBarcodeVerifier(...) / AamvaBarcodeVerifier.Create(...) |
settings.RejectForgedAamvaBarcodes = true + read capturedId.VerificationResult.AamvaBarcodeVerification |
new DataConsistencyVerifier(...) |
settings.RejectInconsistentData = true + read capturedId.VerificationResult.DataConsistency |
NfcScanner / NfcResult / capturedId.Nfc |
(not available on .NET iOS — no NFC API) |
capturedId.VisaDetails / PassportType / MobileDocumentDataElement |
(not available on .NET iOS) |
reading capturedId.Viz.DateOfBirth / .Nationality / .DocumentNumber |
those VIZ fields aren't on .NET — read them from the top-level capturedId.DateOfBirth / .Nationality / .DocumentNumber |
CameraPermissionActivity / runtime permission request (Android) |
declare NSCameraUsageDescription in Info.plist; iOS prompts automatically |
Product Guidance
Apply these rules whenever the user is making a design decision, not just an API question.
- Accept only the documents you actually need. A narrow
AcceptedDocumentslist (e.g. justnew DriverLicense(IdCaptureRegion.Us)) is faster and more accurate thanIdCaptureRegion.Anyacross every document type. Ask the user which documents and regions they expect before defaulting to "everything". - Pick the scanner that matches the data you need.
FullDocumentScanner()reads front and back automatically (best for most ID/DL use cases).SingleSideScanner(barcode, machineReadableZone, visualInspectionZone)reads a single side from the zone(s) you enable — use it when you only need, say, the PDF417 barcode on the back of a US DL, or only the MRZ of a passport.MobileDocumentScanneris for mobile driver's licenses (mDL). - Handle
OnIdRejected, not justOnIdCaptured. Rejections (RejectionReason.Timeout,NotAcceptedDocumentType,DocumentExpired,DocumentVoided,ForgedAamvaBarcode,InconsistentData, …) are how the user learns why a scan didn't succeed. A production integration must surface a message for them. - Anonymize by default if you don't need every field.
IdCaptureSettings.AnonymizationModeand per-field anonymization keep regulated data (document images, sensitive fields) out of the result unless you opt in. Recommend the minimum that satisfies the use case. - Hand off to the
data-capture-sdkskill for non-ID-Capture questions. If the user asks about another Scandit product (Barcode Capture, SparkScan, MatrixScan, Label Capture, etc.) or about choosing between products, defer to thedata-capture-sdkskill instead of guessing.
Intent Routing
Based on the user's request, load the appropriate reference file before responding:
- Integrating ID Capture from scratch, configuring accepted documents and the scanner, creating the mode, hosting the
DataCaptureView+IdCaptureOverlay, wiring the camera lifecycle, handling captured/rejected IDs, and reading the commonCapturedIdfields (e.g. "add passport / driver's license scanning to my .NET iOS app", "read the holder's name and date of birth in C#", "scan an ID card and show the document number") → read references/integration.md and follow it. - Tuning the scanner (single-side / mobile docs), rejection rules (expired / voided / underage / expiring / forged-AAMVA / inconsistent), data-consistency & AAMVA verification, anonymization, reading the rich sub-results (MRZ / VIZ / PDF417 barcode / mobile document / images / driving-license details), or customizing the overlay (e.g. "reject expired IDs", "only read the back barcode of a US license", "verify the AAMVA barcode and detect forgeries", "anonymize the document images", "read the full MRZ", "change the viewfinder style") → read references/advanced.md and follow it.
- Upgrading the Scandit .NET SDK version on an existing ID Capture integration (e.g. "migrate ID Capture from 6.x to 7", "update Scandit to the latest version", "we're on 7.x and the build breaks after bumping the packages", "move off the old
SupportedDocumentsAPI", code that still usesSupportedDocuments/IdDocumentType/SupportedSides, or an app that crashes at launch after an 8.x update) → read references/migration.md and follow it. ID Capture launched ondotnet.iosat 6.16; the 6→7 step is a compile-breaking document/scanner redesign and the 7→8 step requires adding explicit SDK initialization.
API Usage Policy
Only use APIs that are explicitly documented in the Scandit references below. Do not invent or guess method signatures, parameters, property names, or imports. If unsure whether an API exists or how it is called — or if a compile error occurs — fetch the relevant reference page before responding. Do not tell the user to check the docs themselves. After answering, always include the relevant link so the user can explore further.
Never construct or guess documentation URLs. When you need a specific class or property's API page:
- First check whether the page you already fetched contains a direct hyperlink to it — topic pages link directly to relevant API symbols. Always request links alongside content in your fetch prompt.
- If no direct link was found, fetch the API index (see Full API reference in the table below), extract the actual link from it, and follow that.
URL structures can vary (e.g. an api/ui/ subdirectory) and guessing will lead to 404s.
References
Direct users to the right resource based on their question:
| Topic | Resource |
|---|---|
| Get Started | Get Started (.NET for iOS) |
| Advanced topics (scanners, rejection, verification, anonymization, overlay) | Advanced Configurations |
| Migrating / upgrading the SDK version (6→7, 7→8) | references/migration.md · Migrate 6→7 · Migrate 7→8 |
| Full API reference | ID Capture API (.NET iOS) |
API surface this skill covers
All classes documented with :available: dotnet.ios in the official RST docs (docs/source/id-capture/api/**) are addressed in the references. The .NET managed binding is shared across iOS and Android — the API surface is identical; only the platform plumbing (hosting, lifecycle, initialization, camera permission, image type) differs. ID Capture is available on dotnet.ios since 6.16, but the modern document/scanner API (AcceptedDocuments, IdCaptureScanner, FullDocumentScanner) landed at 7.0, the rejection flags at 7.6, and the verification result model at 8.0 — so this skill targets a current 8.x stable.
IdCapture(Scandit.DataCapture.ID.Capture) — staticCreate(DataCaptureContext?, IdCaptureSettings)/Create(IdCaptureSettings);Context(get);Enabled(get/set —falsewhile a result is shown,trueto scan);ApplySettings(IdCaptureSettings);AddListener/RemoveListener(IIdCaptureListener); staticRecommendedCameraSettings(property);Feedback(get/set);Reset();Dispose().IdCaptureSettings—new IdCaptureSettings()then set properties:Scanner(IdCaptureScanner),AcceptedDocuments/RejectedDocuments(IList<IIdCaptureDocument>),RejectVoidedIds,RejectExpiredIds,RejectIdsExpiringIn(Duration?),RejectNotRealIdCompliant,RejectForgedAamvaBarcodes,RejectInconsistentData,RejectHolderBelowAge(int?),DecodeBackOfEuropeanDrivingLicense,AnonymizationMode(IdAnonymizationMode),AnonymizeDefaultFields; methodsAddAnonymizedField(doc, IdFieldType),Get/SetShouldPassImageTypeToResult(IdImageType, bool),SetProperty/GetProperty. No builder.IdCaptureScanner—new IdCaptureScanner(IPhysicalDocumentScanner? physicalDocument, MobileDocumentScanner? mobileDocument);PhysicalDocument/MobileDocument(get).- Physical scanners (
IPhysicalDocumentScanner):new FullDocumentScanner();new SingleSideScanner(bool barcode, bool machineReadableZone, bool visualInspectionZone)(propsBarcode/MachineReadableZone/VisualInspectionZone). MobileDocumentScanner—new MobileDocumentScanner(bool iso180135, bool ocr);Ocr(get). (The ISO getter is bound asGetIso180135— rarely read.)- Documents (
IIdCaptureDocument, propsRegion+DocumentType):new IdCard(IdCaptureRegion),new DriverLicense(IdCaptureRegion),new Passport(IdCaptureRegion),new VisaIcao(IdCaptureRegion),new ResidencePermit(IdCaptureRegion),new HealthInsuranceCard(IdCaptureRegion),new RegionSpecific(RegionSpecificSubtype)(also exposesSubtype). IdCaptureRegionenum —Any,EuAndSchengen, and ~250 PascalCase country values (Us,Uk,Uae,Germany, …).IIdCaptureListener—OnIdCaptured(IdCapture, CapturedId),OnIdRejected(IdCapture, CapturedId?, RejectionReason).CapturedId(Scandit.DataCapture.ID.Data) —FirstName/LastName/FullName,Sex/SexType,DateOfBirth/DateOfExpiry/DateOfIssue(DateResult?),Nationality/NationalityISO,Address,Age(int?),Expired(bool?),Document(IIdCaptureDocument?),IssuingCountry/IssuingCountryIso,DocumentNumber/DocumentAdditionalNumber,Barcode/Mrz/Viz/MobileDocument/MobileDocumentOcr(sub-results),Images(IdImages),VerificationResult,UsRealIdStatus,CitizenPassport,AnonymizedFields; methodsIsRegionSpecific(subtype),IsAnonymized(field).DateResult—Day/Month/Year(int),LocalDate/UtcDate(DateTime).- Sub-results:
MrzResult,VizResult,BarcodeResult(large AAMVA surface),MobileDocumentResult,MobileDocumentOcrResult,DrivingLicenseDetails/DrivingLicenseCategory,ProfessionalDrivingPermit,VehicleRestriction— see references/advanced.md and the docs for full field lists. IdImages—Face,Frame,GetCroppedDocument(IdSide),GetFrame(IdSide)(each aUIKit.UIImage?on iOS).IdCaptureOverlay(Scandit.DataCapture.ID.UI.Overlay) — staticCreate(IdCapture, DataCaptureView?)/Create(IdCapture);IdLayoutStyle(Rounded/Square),IdLayoutLineStyle(Bold/Light),TextHintPosition,ShowTextHints,CapturedBrush/LocalizedBrush/RejectedBrush+ staticDefault*Brush;SetFrontSideTextHint/SetBackSideTextHint.IdCaptureFeedback— staticDefaultFeedback(property);IdCaptured/IdRejected(Feedback).- Verification (
Scandit.DataCapture.ID.Verification) —VerificationResult(DataConsistency/AamvaBarcodeVerification),DataConsistencyResult(AllChecksPassed,FailedChecks/PassedChecks/SkippedChecksasDataConsistencyCheckflags,FrontReviewImageasUIImage?),AamvaBarcodeVerificationResult(AllChecksPassed,Status),AamvaBarcodeVerificationStatus(Authentic/LikelyForged/Forged). No verifier classes — settings-driven. - Enums:
RejectionReason,IdCaptureDocumentType,RegionSpecificSubtype,IdSide,CapturedSides,Sex,UsRealIdStatus,IdAnonymizationMode,IdImageType,IdFieldType.Duration—new Duration(days, months, years).
Documented for other platforms but NOT on dotnet.ios — do not use
- NFC (
NfcScanner,NfcResult,NfcScannerListener,CapturedId.Nfc) — native iOS/Android only; not in the .NET surface. - Deserializer (
IdCaptureDeserializer,IIdCaptureDeserializerListener) — not on .NET. - Standalone
AamvaBarcodeVerifier— web/Xamarin only; on .NET useRejectForgedAamvaBarcodes+CapturedId.VerificationResult. CapturedId.VisaDetails/VisaDetails/ApplicationStatus,PassportType,MobileDocumentDataElement/MobileDocumentScanner.ElementsToRetain,LocalizedOnlyId,BarcodeMetadata,IdCaptureTrigger— not available ondotnet.ios.CapturedId.IsIdCard()/IsPassport()/IsDriverLicense()/ … helper methods — not on .NET; useDocument?.DocumentType.- Most name/identity fields on
VizResult(Sex,DateOfBirth,Nationality,Address,DocumentNumber,DateOfExpiry,DateOfIssue) — not ondotnet.ios; read them from the top-levelCapturedId.
iOS vs Android binding differences (do not cross-pollinate)
DataCaptureViewfactory: iOSDataCaptureView.Create(context, CGRect frame)+this.View.AddSubview(view); AndroidDataCaptureView.Create(context)+container.AddView(view). Using a bareCreate(context)on iOS won't compile, andAddViewdoesn't exist onUIView.- Host & lifecycle: iOS
UIViewController(ViewDidLoad/ViewWillAppear/ViewWillDisappear); AndroidActivity(OnCreate/OnResume/OnPause). NoCameraPermissionActivityon iOS — permission is automatic viaNSCameraUsageDescription. - SDK init: iOS
AppDelegate.FinishedLaunching; AndroidMainApplication.OnCreate. - Main-thread dispatch: iOS
DispatchQueue.MainQueue.DispatchAsync(...)/UIApplication.SharedApplication.InvokeOnMainThread(...); AndroidRunOnUiThread(...). - Listener base class: iOS
NSObject(aUIViewControlleralready is one); AndroidJava.Lang.Object. - Document images: iOS
UIKit.UIImage?; AndroidAndroid.Graphics.Bitmap?.