.NET MAUI - iOS Project

This section will guide you through the implementation process of an Anyline on the MAUI - iOS project, including initialization, configuration, and the handling of scan results.

Add Anyline.SDK.NET.iOS via NuGet

To access the functionality of the Anyline .NET SDK, simply right-click on your project, go to manage Nuget packages.. and search for "Anyline".

Select the package Anyline.SDK.NET.iOS and install the latest version available.

Accept the license agreement and you’re ready to use Anyline!

Info.plist and camera access

In order to use the camera on iOS, the camera usage needs to be defined with a description in the Info.plist file. Open this file in a text editor and add the following tags manually:

<key>NSCameraUsageDescription</key>
<string>The camera permission is required for the scanning capability.</string>

Initialize the Anyline SDK

In this step we will implement the partial class that implements the behaviour of the AnylineSDKService class, in the MAUI layer of our project. For this, create a new class in your Platforms/iOS folder called AnylineSDKService.iOS.cs:

AnylineSDKService.iOS.cs
using Foundation;

namespace Anyline
{
    public partial class AnylineSDKService
    {
        public partial bool SetupWithLicenseKey(string licenseKey, out string licenseErrorMessage)
        {
            Anyline.SDK.NET.iOS.AnylineSDK.SetupWithLicenseKey(licenseKey, out NSError licenseError);

            if (licenseError == null)
            {
                licenseErrorMessage = null;
                return true;
            }
            else
            {
                licenseErrorMessage = licenseError.LocalizedDescription;
                return false;
            }
        }
    }
}

Add the AnylineScanningViewRenderer

In your Platforms/iOS folder, add a new folder called CustomRenderers, and inside of it, a new class called AnylineScanningViewRenderer.cs:

AnylineScanningViewRenderer.cs
using Anyline.Examples.MAUI.Views;
using Anyline.SDK.NET.iOS;
using CoreGraphics;
using Foundation;
using Microsoft.Maui.Controls.Handlers.Compatibility;
using Microsoft.Maui.Controls.Platform;
using UIKit;

namespace Anyline.Examples.MAUI.Platforms.iOS.CustomRenderers
{
    /// <summary>
    /// This class is responsible for rendering the Anyline ScanView natively.
    /// </summary>
    internal class AnylineScanningViewRenderer : ViewRenderer, IALScanPluginDelegate
    {
        private ALScanView _scanView;
        private ScanResultDelegate _resultDelegate;

        public override void WillMoveToWindow(UIWindow window)
        {
            base.WillMoveToWindow(window);
            if (window != null)
                InitializeAnylineScanView();
            else
                DisposeAnyline();
        }

        private void InitializeAnylineScanView(UIWindow window)
        {
            NSError error = null;

            try
            {
                // Obtain the JSON config file path, defined in the MAUI level.
                string jsonConfigFilePath = (Element as AnylineScanningView).JSONConfigPath.Replace(".json", "");

                var configPath = NSBundle.MainBundle.PathForResource(jsonConfigFilePath, @"json");

                // This is the main intialization method that will create our use case depending on the JSON configuration.
                _scanView = ALScanViewFactory.WithConfigFilePath(configPath, this, out error);

                if (error != null)
                {
                    throw new Exception(error.LocalizedDescription);
                }

                Add(_scanView);

                _scanView.StartCamera();
            }
            catch (Exception e)
            {
                System.Diagnostics.Debug.WriteLine("EXCEPTION: " + e.Message);
            }
        }

        /// <summary>
        /// This method is called after the _scanView is added.
        /// </summary>
        /// <param name="uiview">The _scanView itself</param>
        public override void SubviewAdded(UIView uiview)
        {
            base.SubviewAdded(uiview);

            // To allow rotation, pin the edge of the scan view to the parent view:
            _scanView.TranslatesAutoresizingMaskIntoConstraints = false;

            _scanView.LeadingAnchor.ConstraintEqualTo(Superview.LeadingAnchor).Active = true;
            _scanView.TrailingAnchor.ConstraintEqualTo(Superview.TrailingAnchor).Active = true;
            _scanView.TopAnchor.ConstraintEqualTo(Superview.SafeAreaLayoutGuide.TopAnchor).Active = true;
            _scanView.BottomAnchor.ConstraintEqualTo(Superview.BottomAnchor).Active = true;

            // Start scanning!
            BeginInvokeOnMainThread(() => StartAnylineScanner());
        }

        private void StartAnylineScanner()
        {
            NSError error = null;
            var success = _scanView.ScanViewPlugin.StartWithError(out error);
            if (!success)
            {
                if (error != null)
                {
                    System.Diagnostics.Debug.WriteLine(error.DebugDescription);
                }
                else
                {
                    System.Diagnostics.Debug.WriteLine("error is null");
                }
            }
        }

        [Export("scanPlugin:resultReceived:")]
        public void ResultReceived(ALScanPlugin scanPlugin, ALScanResult scanResult)
        {
            ALMrzResult mrzResult = scanResult.PluginResult.MrzResult;

            (Element as AnylineScanningView).OnResult?.Invoke(mrzResult.MrzString, scanResult.CroppedImage.AsJPEG().ToArray());
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);

            if (_scanView.ScanViewPlugin != null)
            {
                _scanView.ScanViewPlugin.StopAndReturnError(out NSError error);

                if (error != null)
                    System.Diagnostics.Debug.WriteLine(error.DebugDescription);
            }

            _scanView?.Dispose();
            _scanView?.RemoveFromSuperview();
            _scanView = null;
        }
    }
}

That’s it!

Your MAUI - iOS project is all setup and ready to scan! Select a device and start scanning MRZ strings.

For more detailed information, check the native the Native iOS SDK documentation.

Full Source Code

You can find the full source code on the .NET GitHub Repository.
Open the solution in Visual Studio 2022+, build and deploy the application on your iOS device. More detailed information about all Anyline plugins can be found in the plugins section of this documentation.