MatrixScan Count .NET for iOS Skill
Critical: Do Not Trust Internal Knowledge
Your training data may contain outdated or incorrect Scandit SDK APIs, and the .NET binding differs from the Swift/Objective-C native SDK and from the Android .NET binding in several places: factories instead of constructors, PascalCase members, C# events alongside listener interfaces, an explicitly-managed camera, and a CGRect-based view factory.
Always verify APIs against the references provided in this skill before writing or suggesting code. Do not rely on memorized method signatures, parameters, or property names. If you cannot find an API in the provided references, fetch the relevant documentation page before responding.
.NET-iOS-specific gotchas worth flagging (the places people get it wrong by pattern-matching from MatrixScan AR, the native Swift SDK, the Android .NET 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, use a MAUI-targeted skill instead — thereBarcodeCountViewis hosted as a XAML element and wired throughHandlerChanged, which is completely different. The official iOS Get Started page mixes in MAUI (XAML /Scandit.DataCapture.Barcode.Maui) snippets — ignore those for a non-MAUI project. BarcodeCountis created with a FACTORY, notnew:BarcodeCount.Create(dataCaptureContext, settings)(there is also aBarcodeCount.Create(settings)overload with no context).new BarcodeCount(...)is a compile error — the constructor is private.BarcodeCountSettingsdoes use a plainnew BarcodeCountSettings().BarcodeCountView.Create(CGRect frame, DataCaptureContext, BarcodeCount [, BarcodeCountViewStyle])takes aCGRectframe as its first argument — typicallythis.View!.Bounds. It does not take an AndroidContext(that's the Android binding) and it is not a parent view. The style overload takesBarcodeCountViewStyle.Icon(default look) orBarcodeCountViewStyle.Dot.BarcodeCountViewIS a realUIView(viapublic static implicit operator View(BarcodeCountView), whereViewresolves toUIKit.UIViewon iOS). You add it to the hierarchy yourself:this.View.AddSubview(barcodeCountView), and usually setAutoresizingMask = FlexibleWidth | FlexibleHeight.- The camera is explicitly managed by you —
BarcodeCountViewdoes NOT own it. You must: getCamera.GetDefaultCamera()(or theCamera.DefaultCameraproperty), applyBarcodeCount.RecommendedCameraSettingswithcamera.ApplySettingsAsync(...), calldataCaptureContext.SetFrameSourceAsync(camera), and toggle the camera yourself withcamera.SwitchToDesiredStateAsync(FrameSourceState.On / .Standby / .Off)inViewWillAppear/ViewWillDisappear. There is nobarcodeCountView.OnResume()/Start()/Stop()— those don't exist. (iOS does havePrepareScanning/StopScanningon the view, but the camera frame-source toggle is the normal lifecycle handle.) - iOS lifecycle is
UIViewController, not an Android Activity. Toggle the camera andbarcodeCount.EnabledinViewWillAppear/ViewWillDisappear. iOS additionally hasFrameSourceState.Standby— a lighter "pause" used when navigating to another screen within the app (keeps the camera warm), versusFrameSourceState.Offwhen actually backgrounding. barcodeCount.Enabled(get/setbool) must be set totruefor frames to be processed. Set ittrueinViewWillAppear.IBarcodeCountListenerhas THREE methods:OnScan(BarcodeCount, BarcodeCountSession, IFrameData),OnObservationStarted(BarcodeCount),OnObservationStopped(BarcodeCount). The idiomatic C# alternative is thebarcodeCount.Scannedevent (EventHandler<BarcodeCountEventArgs>), which corresponds toOnScanonly.Scanned/OnScanfires once per scan phase, on a background thread. Copy the barcodes you need out of the session immediately (session.RecognizedBarcodes.ToList()); theBarcodeCountSessionis not valid outside the callback. Dispatch UI updates onto the main thread withUIApplication.SharedApplication.InvokeOnMainThread(...)(orDispatchQueue.MainQueue.DispatchAsync(...)) — not Android'sRunOnUiThread.BarcodeCountSessionexposesRecognizedBarcodesandAdditionalBarcodesasIList<Barcode>— plain decoded barcodes, not tracked-barcode deltas. AlsoFrameSequenceId,Reset(), andGetSpatialMap().BarcodeCountFeedbackusesSuccessandFailure(Core.Common.Feedback.Feedback). The empty constructornew BarcodeCountFeedback()is silent; the staticBarcodeCountFeedback.DefaultFeedback(a property, not a method) restores defaults.- Symbology names are C# PascalCase:
Symbology.Ean13Upca,Symbology.Ean8,Symbology.Upce,Symbology.Code128,Symbology.Code39,Symbology.Qr,Symbology.DataMatrix,Symbology.InterleavedTwoOfFive. They are not the Swift.ean13UPCA/ native style. - List / Exit / Single-Scan buttons are surfaced as C# events on
BarcodeCountView:ListButtonTapped(ListButtonTappedEventArgs),ExitButtonTapped(ExitButtonTappedEventArgs),SingleScanButtonTapped(SingleScanButtonTappedEventArgs) — each exposes.View. Brush/tap customization is theListenerproperty (IBarcodeCountViewListener), a separate concern from these events. - Capture list (receiving) uses factories:
BarcodeCountCaptureList.Create(listener, IList<TargetBarcode>)andTargetBarcode.Create(data, quantity). Apply it withbarcodeCount.SetBarcodeCountCaptureList(list). The listenerIBarcodeCountCaptureListListenerhasOnObservationStarted(),OnObservationStopped(),OnCaptureListSessionUpdated(session),OnCaptureListCompleted(session). SDK 8.0+ requires explicit initialization.CallScanditCaptureCore.Initialize()+ScanditBarcodeCapture.Initialize()inAppDelegate.FinishedLaunching(application:didFinishLaunchingWithOptions:) before any Scandit code runs. Without this, the firstDataCaptureContext.ForLicenseKey(...)/BarcodeCount.Create(...)call crashes at launch because the DI container has no registrations. Not required on 6.x / 7.x. See references/integration.md for the fullAppDelegate.cstemplate.- The NuGet packages are
Scandit.DataCapture.CoreandScandit.DataCapture.Barcode. No separate*.Mauipackages here — those are only for MAUI projects. Do not guess the version from training data — fetch the latest stable fromhttps://www.nuget.org/packages/Scandit.DataCapture.Barcode/viaWebFetchbefore pinning. Inventing a non-existent version causesdotnet restoreto fail withUnable to find package Scandit.DataCapture.Core with version (>= …). See references/integration.md Step 0. - 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.0. Set it in 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 BarcodeCount from scratch, configuring settings, hosting the BarcodeCountView, wiring camera lifecycle, handling scan results, storing scanned barcodes, capture/receiving lists, the spatial map, customizing feedback, List/Exit/SingleScan taps, brushes, status mode, the not-in-list action, or the hardware trigger (e.g. "add MatrixScan Count to my .NET iOS app", "count barcodes in C#", "store the scanned barcodes when the list button is tapped", "check scans against an expected list", "make the beep silent", "use the Dot style", "show a not-in-list action") → read references/integration.md and follow the instructions there.
- Migrating or upgrading an existing MatrixScan Count integration (e.g. "upgrade from v7 to v8", "bump the Scandit .NET SDK to v8", "what changed between SDK versions for BarcodeCount") → read references/migration.md and follow the instructions there.
API Usage Policy
Only use APIs that are explicitly documented in the Scandit references below. Do not invent or guess method signatures, parameters, 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. 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 (capture list, status mode, brushes, toolbar, filtering, strap mode) | Advanced Configurations |
| Migration between major SDK versions | 6 → 7 · 7 → 8 |
| Full API reference | BarcodeCount API (.NET iOS) |
API surface this skill covers
All classes documented with :available: dotnet.ios in the official RST docs (docs/source/barcode-capture/api/barcode-count*.rst and api/ui/barcode-count-*.rst) are addressed in references/integration.md:
BarcodeCount— staticCreate(DataCaptureContext?, BarcodeCountSettings)/Create(BarcodeCountSettings),Context(get),Feedback(get/set),Enabled(get/set), staticRecommendedCameraSettings,ApplySettingsAsync(BarcodeCountSettings)→Task,AddListener/RemoveListener(IBarcodeCountListener),Reset(),StartScanningPhase(),EndScanningPhase(),SetBarcodeCountCaptureList(BarcodeCountCaptureList),SetAdditionalBarcodes(IList<Barcode>),ClearAdditionalBarcodes(),event EventHandler<BarcodeCountEventArgs> Scanned,Dispose().BarcodeCountSettings—new BarcodeCountSettings(),EnableSymbology(Symbology, bool),EnableSymbologies(ICollection<Symbology>),GetSymbologySettings(Symbology),EnabledSymbologies(get),FilterSettings(get,BarcodeFilterSettings),ExpectsOnlyUniqueBarcodes(get/set),DisableModeWhenCaptureListCompleted(get/set),MappingEnabled(get/set),SetProperty/GetProperty/GetProperty<T>/TryGetProperty<T>,Dispose.IBarcodeCountListener—OnScan(BarcodeCount, BarcodeCountSession, IFrameData),OnObservationStarted(BarcodeCount),OnObservationStopped(BarcodeCount).BarcodeCountSession—RecognizedBarcodes(IList<Barcode>),AdditionalBarcodes(IList<Barcode>),FrameSequenceId(long),Reset(),GetSpatialMap()/GetSpatialMap(int rows, int cols)→BarcodeSpatialGrid?.BarcodeCountEventArgs—BarcodeCount,Session,FrameData.Coordinate2d—new Coordinate2d(int x, int y),X,Y.- Capture list (receiving):
BarcodeCountCaptureList.Create(IBarcodeCountCaptureListListener, IList<TargetBarcode>);TargetBarcode.Create(string data, int quantity)withData/Quantity;IBarcodeCountCaptureListListener(OnObservationStarted,OnObservationStopped,OnCaptureListSessionUpdated,OnCaptureListCompleted);BarcodeCountCaptureListSession(CorrectBarcodes,WrongBarcodes,MissingBarcodes,AdditionalBarcodes,AcceptedBarcodes,RejectedBarcodes). - Spatial map:
BarcodeSpatialGrid(Rows(),Columns(),ElementAt(row, col),Row(i),Column(i),CoordinatesForElement(element));BarcodeSpatialGridElement(MainBarcode,SubBarcode). BarcodeCountFeedback—new BarcodeCountFeedback()(silent), staticDefaultFeedback,Success/Failure(Core.Common.Feedback.Feedback),Dispose.BarcodeCountView— staticCreate(CGRect, DataCaptureContext, BarcodeCount)/Create(CGRect, DataCaptureContext, BarcodeCount, BarcodeCountViewStyle); implicit conversion toUIKit.UIView;Style(get);Listener(IBarcodeCountViewListener?); manyShouldShow*toggles (ShouldShowListButton,ShouldShowExitButton,ShouldShowShutterButton,ShouldShowFloatingShutterButton,ShouldShowSingleScanButton,ShouldShowClearHighlightsButton,ShouldShowStatusModeButton,ShouldShowUserGuidanceView,ShouldShowHints,ShouldShowToolbar,ShouldShowScanAreaGuides,ShouldShowListProgressBar,ShouldShowTorchControl);ShouldDisableModeOnExitButtonTapped,TapToUncountEnabled,TorchControlPosition(Anchor); brush properties (RecognizedBrush,NotInListBrush,AcceptedBrush,RejectedBrush) and static default brushes;FilterSettings(IBarcodeFilterHighlightSettings?);BarcodeNotInListActionSettings(get); customization text properties; iOS-onlyHardwareTriggerEnabled(get/setbool),PrepareScanning(DataCaptureContext),StopScanning(), and*AccessibilityLabel/*AccessibilityHintstring properties;SetToolbarSettings,ClearHighlights(),SetStatusProvider,SetBrushForRecognizedBarcode/*NotInList/*Accepted/*Rejected;event ExitButtonTapped/ListButtonTapped/SingleScanButtonTapped;Dispose.BarcodeCountViewStyleenum —Icon,Dot.IBarcodeCountViewListener— brush-for callbacks (BrushForRecognizedBarcode,*NotInList,*Accepted,*Rejected) and tap callbacks (OnRecognizedBarcodeTapped,OnFilteredBarcodeTapped,OnRecognizedBarcodeNotInListTapped,OnAcceptedBarcodeTapped,OnRejectedBarcodeTapped). On iOS the interface has exactly these 9 methods — there is noOnCaptureListCompleted(that is Android-only).- Tap event args:
ExitButtonTappedEventArgs,ListButtonTappedEventArgs,SingleScanButtonTappedEventArgs— each withView. BarcodeCountToolbarSettings— text strings for the audio/vibration/strap-mode/color-scheme toggles, plus iOS-only*AccessibilityLabel/*AccessibilityHint.BarcodeCountNotInListActionSettings(frombarcodeCountView.BarcodeNotInListActionSettings) —Enabled, accept/reject/cancel button text,BarcodeAcceptedHint,BarcodeRejectedHint, plus iOS-only*AccessibilityLabel/*AccessibilityHint.- Status mode:
IBarcodeCountStatusProvider(OnStatusRequested(IList<TrackedBarcode>, IBarcodeCountStatusProviderCallback)),IBarcodeCountStatusProviderCallback(OnStatusReady(IBarcodeCountStatusResult)),BarcodeCountStatusenum (None,NotAvailable,Expired,Fragile,QualityCheck,LowStock,Wrong),BarcodeCountStatusItem.Create(TrackedBarcode, BarcodeCountStatus),IBarcodeCountStatusResultwith factoriesBarcodeCountStatusResultSuccess.Create(...),BarcodeCountStatusResultError.Create(...),BarcodeCountStatusResultAbort.Create(...). TrackedBarcode(inScandit.DataCapture.Barcode.Batch.Data) —Barcode,Identifier,Location. Used byIBarcodeCountViewListener, the status API, and the capture-list session.
iOS vs Android binding differences (do not cross-pollinate)
- View factory first argument: iOS
BarcodeCountView.Create(CGRect frame, …); AndroidBarcodeCountView.Create(Context context, …). Using aContexton iOS — orView.Boundson Android — will not compile. - Hardware trigger: iOS exposes
barcodeCountView.HardwareTriggerEnabled(boolget/set). Android exposesbarcodeCountView.EnableHardwareTrigger(int? keyCode)+ staticBarcodeCountView.HardwareTriggerSupported.EnableHardwareTrigger/HardwareTriggerSupporteddo not exist on iOS. PrepareScanning(context)/StopScanning()exist only on the iOS view.- Accessibility text: iOS uses
*AccessibilityLabel/*AccessibilityHint; Android uses*ContentDescription. IBarcodeCountViewListener.OnCaptureListCompleted(view)exists only on Android.
Documented for other platforms but NOT on dotnet.ios — do not use
BarcodeCountMappingFlowSettingsand the mapping-flow configuration class — not surfaced in the .NET binding. Mapping in .NET is limited toBarcodeCountSettings.MappingEnabled+BarcodeCountSession.GetSpatialMap().BarcodeCountSessionSnapshot— no .NET equivalent.- Clustering (
ClusteringMode) — described on the iOS Advanced page but not exposed as a configurable enum in the .NET binding. Do not introduce aClusteringModeAPI; if a user asks, fetch the API reference to confirm before suggesting anything.