Label Capture (Smart Label Capture) .NET for iOS Skill
Critical: Do Not Trust Internal Knowledge
Your training data may contain outdated or incorrect Scandit Label Capture APIs, and the .NET binding differs substantially from the Swift/Objective-C native iOS SDK and from the .NET for Android binding. An agent that pattern-matches from the native iOS (Swift) Label Capture docs will get nearly every call wrong, because the .NET binding does not use the Swift fluent settings builder — it builds each field with a per-field factory and assembles a list of definitions.
Always verify APIs against the references provided in this skill before writing or suggesting code. Do not rely on memorized method signatures, parameters, or builder 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 SDK, the .NET Android binding, or MAUI:
- 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. - There is NO
LabelCaptureSettings.builder()fluent chain. The Swift/Kotlin patternLabelCaptureSettings.settings { ... }/builder().addLabel()...buildFluent(...).build()does not exist in .NET. Instead you: (1) build each field via its own factory, (2) collect them in aList<LabelFieldDefinition>, (3)LabelDefinition.Create(name, fields), (4)LabelCaptureSettings.Create(new List<LabelDefinition> { def }). - Each field type is built with a static
Builder()factory, then.Build("field-name"):CustomBarcode.Builder().SetSymbologies(IList<Symbology>).Build("Barcode"),ExpiryDateText.Builder().SetLabelDateFormat(...).Build("Expiry Date"),TotalPriceText.Builder().IsOptional(true).Build("Total Price"),CustomText.Builder().SetValueRegex("...").Build("Lot"). The builder is shared-generic, soIsOptional(bool),SetValueRegex(es),SetNumberOfMandatoryInstances(int?)are available on every field builder;SetSymbology(ies)on barcode builders;SetAnchorRegex(es)/SetLocation(...)on custom fields. LabelCaptureis created with a FACTORY, notnewand notforDataCaptureContext:LabelCapture.Create(dataCaptureContext, settings). The constructor is private.DataCaptureView.Create(DataCaptureContext, CGRect frame)takes aCGRectas its second argument on iOS — typicallythis.View!.Bounds. 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).- Symbology names are C# PascalCase:
Symbology.Ean13Upca,Symbology.Gs1DatabarExpanded,Symbology.Code128,Symbology.Code39,Symbology.Qr,Symbology.DataMatrix. They are not the Swift.ean13UPCA/.code128style.Symbologylives inScandit.DataCapture.Barcode.Data. SetSymbologiestakes anIList<Symbology>(e.g.new List<Symbology> { ... }), not a vararg. For one symbology useSetSymbology(Symbology).- Only THREE NuGet packages, no separate text-models package.
Scandit.DataCapture.Core,Scandit.DataCapture.Barcode, andScandit.DataCapture.Label. Text fields (expiry date, price, weight, custom text) are bundled inScandit.DataCapture.Label— there is nolabel-text-modelsartifact like on native iOS. (Barcodeis always required becauseSymbologyand the barcode field types live there.) Do not add any*.Mauipackage. - SDK 8.0+ requires explicit initialization with THREE initializers in
AppDelegate.FinishedLaunching(application:didFinishLaunchingWithOptions:):ScanditCaptureCore.Initialize(),ScanditBarcodeCapture.Initialize(), andScanditLabelCapture.Initialize()before any Scandit type is constructed. Missing the Label one crashes the firstLabelCapture.Create(...)call. Label Capture is only available ondotnet.iossince 8.2, so this initializer always applies. - You manage the camera yourself; the view does not own it.
Camera.GetDefaultCamera(LabelCapture.RecommendedCameraSettings),dataCaptureContext.SetFrameSourceAsync(camera), thencamera.SwitchToDesiredStateAsync(FrameSourceState.On / .Standby / .Off)across theUIViewControllerlifecycle.RecommendedCameraSettingsis a static property onLabelCapture, not a method. iOS additionally hasFrameSourceState.Standby(a lighter pause for in-app navigation, keeps the camera warm) versus.Offwhen backgrounding. - iOS lifecycle is
UIViewController, not an Android Activity. Toggle the camera andlabelCapture.EnabledinViewWillAppear/ViewWillDisappear. KeepViewDidLoadsynchronous (fire-and-forget the async camera setup) — anasync void ViewDidLoadreturns to UIKit at the firstawait, soViewWillAppearruns before the mode/camera are constructed. ILabelCaptureListener.OnSessionUpdated(LabelCapture, LabelCaptureSession, IFrameData)is the result callback (plus optionalOnObservationStarted/OnObservationStopped). The idiomatic C# alternative is thelabelCapture.SessionUpdatedevent (EventHandler<LabelCaptureEventArgs>).OnSessionUpdatedruns on a background thread — dispatch UI work to the main thread withUIApplication.SharedApplication.InvokeOnMainThread(...)orDispatchQueue.MainQueue.DispatchAsync(...)(not Android'sRunOnUiThread), and setlabelCapture.Enabled = falseafter a successful capture to avoid re-capturing the same label. A listener implementation derives fromNSObject(not Android'sJava.Lang.Object).- Read field values via
LabelField:field.Name,field.Barcode?.Data(aBarcode?),field.Text(astring?),field.Date(aLabelDate?withYear/Month/Dayints and*Stringaccessors). On iOS there is an extrafield.ValueType(LabelFieldValueType:Date/Price/Weight/Text/Numeric) that does not exist on .NET Android. Match fields by the exactNameyou passed to.Build("...").CapturedLabelexposesFields,Name,Complete,TrackingId.LabelCaptureSession.CapturedLabelsis anIList<CapturedLabel>. LabelCaptureFeedbackexposes a singleSuccessslot (Core.Common.Feedback.Feedback) plus the staticLabelCaptureFeedback.Default(a property). To customize:var fb = LabelCaptureFeedback.Default; fb.Success = new Feedback(Vibration.DefaultVibration, null); labelCapture.Feedback = fb;.- 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.
Intent Routing
Based on the user's request, load the appropriate reference file before responding:
- Integrating Label Capture from scratch, defining the label (fields, symbologies, regexes, optional vs required), creating the mode, hosting the
DataCaptureView+LabelCaptureBasicOverlay, wiring the camera lifecycle, handling captured labels, customizing feedback or brushes, or using prebuilt definitions (VIN / price label / 7-segment) (e.g. "add Smart Label Capture to my .NET iOS app", "scan a barcode and an expiry date from a price tag in C#", "read the total price field", "use the recommended camera settings") → read references/integration.md and follow it. - Enabling or customizing the Validation Flow (e.g. "add the guided validation flow so users can review and correct fields", "let the user type a field that didn't scan", "customize the validation-flow hint text / button labels") → read references/validation-flow.md and follow it.
- Customizing overlay appearance (per-field / per-label brushes, tap handling), adding an advanced overlay with custom native views over labels (AR), enabling Adaptive Recognition cloud fallback (beta), or Receipt Scanning (beta) (e.g. "tint the barcode highlight a different color than the expiry date", "show a warning view under expiry dates close to expiring", "add cloud fallback / ARE", "scan receipts") → read references/advanced-overlays.md and follow it. Adaptive Recognition and Receipt Scanning are beta and subscription-gated — always flag this.
API Usage Policy
Only use APIs that are explicitly documented in the Scandit references below. Do not invent or guess method signatures, parameters, builder shapes, or property names. 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) |
| Label Definitions (fields, regex, presets) | Label Definitions |
| Advanced topics (Validation Flow, adaptive recognition, advanced overlay) | Advanced Configurations |
| Full API reference | Label Capture API (.NET iOS) |
API surface this skill covers
All classes documented with :available: dotnet.ios in the official RST docs (docs/source/label-capture/api/**) are addressed in the references. Label Capture is available on dotnet.ios since 8.2.
LabelCapture— staticCreate(DataCaptureContext?, LabelCaptureSettings),Context(get),Enabled(get/set — settrueto process frames,falseafter a capture),ApplySettingsAsync(LabelCaptureSettings)→Task,AddListener/RemoveListener(ILabelCaptureListener), staticRecommendedCameraSettings(property),Feedback(get/set),event EventHandler<LabelCaptureEventArgs> SessionUpdated,Dispose().LabelCaptureSettings— staticCreate(IList<LabelDefinition>),LocationSelection(get/set,ILocationSelection?),GetSymbologySettings(Symbology),SetProperty/GetProperty/GetProperty<T>/TryGetProperty<T>,Dispose. No settings builder.LabelCaptureSession—CapturedLabels(IList<CapturedLabel>),FrameSequenceId(long),LastProcessedFrameId(int).ILabelCaptureListener—OnSessionUpdated(LabelCapture, LabelCaptureSession, IFrameData), optionalOnObservationStarted(LabelCapture)/OnObservationStopped(LabelCapture). Implementations derive fromNSObject.LabelCaptureEventArgs—Mode,Session,FrameData.LabelDefinition— staticCreate(string name, IList<LabelFieldDefinition>); prebuiltCreateVinLabelDefinition(name),CreatePriceCaptureDefinition(name),CreateSevenSegmentDisplayLabelDefinition(name);Name,Fields,AdaptiveRecognitionMode(get/set),HiddenProperties.LabelDefinitionBuilder—AddCustomBarcode/AddSerialNumberBarcode/AddPartNumberBarcode/AddImeiOneBarcode/AddImeiTwoBarcode/AddCustomText/AddExpiryDateText/AddPackingDateText/AddDateText/AddTotalPriceText/AddUnitPriceText/AddWeightText,AdaptiveRecognition(AdaptiveRecognitionMode),SetHiddenProperty/Properties,Build(name). (An alternative to passing the list directly toLabelDefinition.Create.)- Field types, each with a static
Builder()returning a fluent builder andBuild(string name):- Barcode fields:
CustomBarcode(SetSymbologies(IList<Symbology>)/SetSymbology(Symbology),SetAnchorRegex(es),SetLocation(...)),SerialNumberBarcode,PartNumberBarcode,ImeiOneBarcode,ImeiTwoBarcode(preset symbologies/regexes). - Text fields:
CustomText(SetValueRegex(es),SetAnchorRegex(es),SetLocation(...)),ExpiryDateText/PackingDateText/DateText(SetLabelDateFormat(LabelDateFormat)),TotalPriceText,UnitPriceText,WeightText. - Shared builder members (on all):
IsOptional(bool),SetValueRegex(string)/SetValueRegexes(IList<string>),SetNumberOfMandatoryInstances(int?),SetHiddenProperty/Properties.
- Barcode fields:
CapturedLabel—Fields(IReadOnlyList<LabelField>),Name,Complete(bool),PredictedBounds(Quadrilateral),DeltaTimeToPrediction,TrackingId(int).LabelField—Name,Type(LabelFieldType:Barcode/Text/Unknown),ValueType(LabelFieldValueType:Date/Price/Weight/Text/Numeric, iOS-only),State(LabelFieldState:Captured/Predicted/Unknown),Required(bool),Barcode(Barcode?),Text(string?),Date(LabelDate?),PredictedLocation(Quadrilateral).LabelDate—Year/Month/Day(int?),DayString/MonthString/YearString.LabelDateFormat—new LabelDateFormat(LabelDateComponentFormat, bool acceptPartialDates),ComponentFormat,AcceptPartialDates.LabelDateComponentFormatenum (component ordering, e.g.MDY/DMY/YMD).LabelCaptureBasicOverlay— staticCreate(LabelCapture)/Create(LabelCapture, DataCaptureView?);Listener(ILabelCaptureBasicOverlayListener?);SetBrushForField/SetBrushForLabel;PredictedFieldBrush/CapturedFieldBrush/LabelBrush(get/set) + staticDefault*Brush;GetFieldBrush/SetFieldBrush(LabelFieldState, Brush?);ShouldShowScanAreaGuides;Viewfinder(IViewfinder?);Dispose.ILabelCaptureBasicOverlayListener—BrushForField(overlay, field, label),BrushForLabel(overlay, label),OnLabelTapped(overlay, label).- Validation Flow (see references/validation-flow.md):
LabelCaptureValidationFlowOverlay(staticCreate(LabelCapture, DataCaptureView?),Listener,ApplySettings;OnResume/OnPauseandShouldHandleKeyboardInsetsInternallyexist but are Android-only no-ops on iOS),LabelCaptureValidationFlowSettings(staticCreate(), hint/button text props,SetPlaceholderText/GetPlaceholderText),ILabelCaptureValidationFlowListener(OnValidationFlowLabelCaptured(IList<LabelField>),OnManualInputSubmitted,OnValidationFlowResultUpdate),LabelResultUpdateType. LabelCaptureFeedback— staticDefault(property),Success(Core.Common.Feedback.Feedback),Dispose.AdaptiveRecognitionModeenum — controls cloud-backed recognition for a definition (Offdefault).
Advanced topics (available on dotnet.ios but intentionally deferred to the docs)
These are real dotnet.ios symbols but out of scope for a first integration — don't invent their shapes; fetch the Advanced Configurations page if the user asks for them:
- Adaptive Recognition (cloud backup):
LabelCaptureAdaptiveRecognitionOverlay,LabelCaptureAdaptiveRecognitionSettings,ILabelCaptureAdaptiveRecognitionListener, and the result typesAdaptiveRecognitionResult/AdaptiveRecognitionResultType/ReceiptScanningResult/ReceiptScanningLineItem. Enabled per-definition viaAdaptiveRecognitionMode. - Advanced overlay (arbitrary native views over labels):
LabelCaptureAdvancedOverlay,ILabelCaptureAdvancedOverlayListener. LabelFieldLocation/LabelFieldLocationType— used withSetLocation(...)on custom field builders to constrain where a field is expected on the label.
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
UIApplication.SharedApplication.InvokeOnMainThread(...)/DispatchQueue.MainQueue.DispatchAsync(...); AndroidRunOnUiThread(...). - Listener base class: iOS
NSObject; AndroidJava.Lang.Object. LabelField.ValueType(LabelFieldValueType) is iOS-only — it does not exist on .NET Android.- Validation Flow lifecycle:
overlay.OnResume()/overlay.OnPause()andShouldHandleKeyboardInsetsInternallyare Android-specific — on iOS they are no-ops. Do not call them in an iOS integration.