The Anyline SDK
This section describes how to implement and use the Anyline SDK in your iOS application.
Overview
Anyline consists of a number of components working together to accomplish a scan. Each component corresponds in the iOS SDK to a class or protocol in Swift as well as in Objective-C.
The SDK classes you are most likely to interact with would be the ALScanView
and the ALScanPluginDelegate
:
-
ALScanView - a UIView that contains the scanning interface: a camera view as well as a flash/torch component.
-
ALScanPluginDelegate - a protocol containing methods allowing the delegate to handle the received scan result.
In addition, depending on your specific needs your code may also need to directly (or indirectly) interact with some additional components:
-
ALViewPluginBase - a protocol an instance (or instances) of whom is held by an ALScanView, defining functionality implemented by both ALScanViewPlugin and ALViewPluginComposite.
-
ALScanViewPlugin - an object responsible for the scan view user interface and visual feedback elements.
-
ALViewPluginComposite - an object running multiple instances of ALScanViewPlugin.
-
ALScanPlugin - an object held by
ALScanViewPlugin
, which handles the scanning capabilities as well as low-level image processing, and which sends any scan results back to its ALScanPluginDelegate.
Adding Anyline to your Scanning Workflow
By this time, you should already have initialized the Anyline SDK with the license key for your application. For more details, please see Initialize the Anyline SDK. |
For the code snippets below, and the ones the follow, it is assumed that the Anyline framework has been imported into the source code where you are using Anyline:
-
Swift
-
Objective-C
import Anyline
#include <Anyline/Anyline.h>
Add the ScanView to your view hierarchy
To present a scan view with your configuration, a configured ALScanView
needs to be added to a UIViewController
's view hierarchy.
The simplest and recommended way to do so is to create an ALScanView
with a factory method. In viewDidLoad
,
-
Swift
-
Objective-C
let JSONStr = "{\"viewPluginConfig\":{\"pluginConfig\":{\"tinConfig\":{\"scanMode\":\"DOT\"},\"cancelOnResult\":true},\"scanFeedbackConfig\":{\"style\":\"contour_rect\"}}}"
do {
self.scanView = try ALScanViewFactory.withJSONString(JSONStr, delegate: self)
} catch {
// handle the error
}
if let scanView = self.scanView {
// add scan view to the view hierarchy
view.addSubview(scanView)
// set the scan view's frame (either programmatically or via AutoLayout)
scanView.frame = view.frame
// ...
scanView.startCamera()
}
NSString JSONString = @"{\"viewPluginConfig\":{\"pluginConfig\":{\"tinConfig\":{\"scanMode\":\"DOT\"},\"cancelOnResult\":true},\"scanFeedbackConfig\":{\"style\":\"contour_rect\"}}}";
NSError *error;
self.scanView = [ALScanViewFactory withJSONString:JSONString delegate:self error:&error];
if (self.scanView) {
[self addScanViewToViewHierarchy(self.scanView);
[self.scanView startCamera];
}
Starting Anyline 53, changes have been made to the way in which a ScanView is constructed and set up. For more information, please refer to Migrating to Anyline 53. |
While creating each component, it is recommended that you handle any errors during any class’s initializer. For instance with Swift, use a Note that if an error object has been passed back with a non-null value, then the object associated with the initializer was likely not successfully created, so the error object can provide some insight into the problem and potentially suggest a course of action. |
The above example creates an ALScanView
configured with the included JSON string, which should be a valid Anyline config. If the string is not a valid config, the view will not be created, and an error would be thrown. You would then need to provide a way to handle this error.
Do not forget to also add the ALScanView
to your view hierarchy and configure it as you would with any other UIView
object (including setting its frame), and then call its startCamera
method.
In addition, you should implement the ALScanPluginDelegate
protocol in your delegate class (here it would be the UIViewController) and then start the scanning process (refer to the following sections).
Start the Scanning Process
To start the scanning process, simply call the startScanning
method from the ScanView (typically after its camera has been started). Doing so will begin to process the frame images that are provided by the device’s camera module.
-
Swift
-
Objective-C
do {
try self.scanView.startScanning()
} catch {
// handle any errors
}
NSError *error;
[scanViewPlugin startWithError:&error];
// handle any errors
Implement the ScanPluginDelegate
After some time, assuming conditions for a successful scan are met, results from a scan will be returned by Anyline.
To use the results obtained from the scanning process, have your UIViewController
or another object implement the ALScanPluginDelegate
protocol:
-
Swift
-
Objective-C
class MeterScanViewController: UIViewController, ALScanPluginDelegate { … }
@interface MeterScanViewController: UIViewController <ALScanPluginDelegate>
Then, implement a number of methods from this protocol. This will be discussed in more detail in a subsequent section. At the very least, have your delegate implement the scanPlugin(_:resultReceived:)
: method (the scanResult
parameter and more specifically its pluginResult
object holds the results of the scan process):
-
Swift
-
Objective-C
func scanPlugin(_ scanPlugin: ALScanPlugin, resultReceived scanResult: ALScanResult) {
print("the result: \(scanResult.pluginResult.meterResult?.value ?? "")")
}
- (void)scanPlugin:(ALScanPlugin *)scanPlugin resultReceived:(ALScanResult *)scanResult {
NSLog(@"the result: ", scanResult.pluginResult.meterResult.value);
}
Complete Source Code
The source code for the above example is shown here:
-
Swift
-
Objective-C
import Anyline
class MeterScanViewController: UIViewController {
fileprivate var scanView: ALScanView!
override func viewDidLoad() {
super.viewDidLoad()
let JSONStr = """
{\"viewPluginConfig\":{\"pluginConfig\":{\"id\":\"meter_auto\",\"meterConfig\":{\"scanMode\":\"auto_analog_digital_meter\"},\"cancelOnResult\":true},\"cutoutConfig\":{\"maxWidthPercent\":\"80%\",\"ratioFromSize\":{\"width\":3,\"height\":1}},\"scanFeedbackConfig\":{}}}
"""
do {
self.scanView = try ALScanViewFactory.withJSONString(JSONStr, delegate: self)
self.installScanView(scanView)
self.scanView.startCamera()
try self.scanView?.startScanning()
} catch {
print("error: \(error.localizedDescription)")
}
}
fileprivate func installScanView(_ scanView: ALScanView) {
self.view.addSubview(scanView)
scanView.translatesAutoresizingMaskIntoConstraints = false
scanView.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true
scanView.rightAnchor.constraint(equalTo: self.view.rightAnchor).isActive = true
scanView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
scanView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
}
}
extension MeterScanViewController: ALScanPluginDelegate {
func scanPlugin(_ scanPlugin: ALScanPlugin, resultReceived scanResult: ALScanResult) {
print(scanResult.pluginResult.meterResult?.value ?? "")
}
}
#import <Anyline/Anyline.h>
@interface MeterScanViewController : UIViewController <ALScanPluginDelegate>
@property (nonatomic, strong) ALScanView *scanView;
@end
@implementation MeterScanViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSString *config = @"{\"viewPluginConfig\":{\"pluginConfig\":{\"id\":\"meter_auto\",\"meterConfig\":{\"scanMode\":\"auto_analog_digital_meter\"},\"cancelOnResult\":true},\"cutoutConfig\":{\"maxWidthPercent\":\"80%\",\"ratioFromSize\":{\"width\":3,\"height\":1}},\"scanFeedbackConfig\":{}}}";
NSError *error;
self.scanView = [ALScanViewFactory withJSONString:config delegate:self error:&error];
if (!self.scanView) {
// handle error
}
[self installScanView:self.scanView];
[self.scanView startCamera];
BOOL success = [self.scanView startScanningWithError:&error];
if (success) {
// handle error
}
}
// MARK: - Handle & present results
- (void)installScanView:(ALScanView *)scanView {
[self.view addSubview:scanView];
scanView.translatesAutoresizingMaskIntoConstraints = false;
[scanView.leftAnchor constraintEqualToAnchor:self.view.leftAnchor].active = YES;
[scanView.rightAnchor constraintEqualToAnchor:self.view.rightAnchor].active = YES;
[scanView.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor].active = YES;
[scanView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor].active = YES;
}
- (void)scanPlugin:(ALScanPlugin *)scanPlugin resultReceived:(ALScanResult *)scanResult {
NSLog(@"result: %@", scanResult.pluginResult.meterResult.value);
}
@end
Questions or need further assistance? Please reach out to the Anyline Support Helpdesk.