diff --git a/AnylineExamples/Anyline Demo App/DemoApp Source/Models/ALExampleManager.h b/AnylineExamples/Anyline Demo App/DemoApp Source/Models/ALExampleManager.h
index 3efba74ac..cb135d83f 100755
--- a/AnylineExamples/Anyline Demo App/DemoApp Source/Models/ALExampleManager.h
+++ b/AnylineExamples/Anyline Demo App/DemoApp Source/Models/ALExampleManager.h
@@ -25,5 +25,3 @@
- (ALExample *)exampleForIndexPath:(NSIndexPath *)indexPath;
@end
-
-extern NSString * const processTitle;
diff --git a/AnylineExamples/Anyline Demo App/DemoApp Source/Models/ALExampleManager.m b/AnylineExamples/Anyline Demo App/DemoApp Source/Models/ALExampleManager.m
index 53cc511da..3afa046bc 100755
--- a/AnylineExamples/Anyline Demo App/DemoApp Source/Models/ALExampleManager.m
+++ b/AnylineExamples/Anyline Demo App/DemoApp Source/Models/ALExampleManager.m
@@ -22,8 +22,6 @@
#import "ALDocumentScanViewController.h"
#import "ALLicensePlateViewController.h"
-NSString * const processTitle = @"Processes";
-
@interface ALExampleManager ()
@property (nonatomic, strong) NSDictionary *examples;
diff --git a/AnylineExamples/Anyline Demo App/DemoApp Source/Models/ALMeterExampleManager.m b/AnylineExamples/Anyline Demo App/DemoApp Source/Models/ALMeterExampleManager.m
index aad500f01..032ce70e7 100644
--- a/AnylineExamples/Anyline Demo App/DemoApp Source/Models/ALMeterExampleManager.m
+++ b/AnylineExamples/Anyline Demo App/DemoApp Source/Models/ALMeterExampleManager.m
@@ -44,26 +44,15 @@ - (void)initExampleData {
image:[UIImage imageNamed:@"dial meter"]
viewController:[ALDialMeterScanViewController class]];
-
- ALExample *selfScanning = [[ALExample alloc] initWithName:NSLocalizedString(@"Self Reading", nil)
- image:[UIImage imageNamed:@"Self Reading"]
- viewController:[CustomerSelfReadingViewController class]];
-
- ALExample *workforce = [[ALExample alloc] initWithName:NSLocalizedString(@"Workforce", nil)
- image:[UIImage imageNamed:@"Workforce"]
- viewController:[WorkForceViewController class]];
-
ALExample *serialScanning = [[ALExample alloc] initWithName:NSLocalizedString(@"Serial Number", nil)
image:[UIImage imageNamed:@"serial number"]
viewController:[ALMeterSerialNumberScanViewController class]];
- self.sectionNames = @[@"Meter Types", @"Processes", @"Others"];
+ self.sectionNames = @[@"Meter Types"];
self.examples = @{
self.sectionNames[0] : @[autoAnalogDigitalMeterScanning,
- dialMeterScanning,],
- self.sectionNames[1] : @[selfScanning,
- workforce,],
- self.sectionNames[2] : @[serialScanning,],
+ dialMeterScanning,
+ serialScanning]
};
}
diff --git a/AnylineExamples/Anyline Demo App/DemoApp Source/Models/ALOthersExampleManager.m b/AnylineExamples/Anyline Demo App/DemoApp Source/Models/ALOthersExampleManager.m
index 3514de2f0..595a2391f 100644
--- a/AnylineExamples/Anyline Demo App/DemoApp Source/Models/ALOthersExampleManager.m
+++ b/AnylineExamples/Anyline Demo App/DemoApp Source/Models/ALOthersExampleManager.m
@@ -21,6 +21,8 @@
#import "ALCattleTagScanViewController.h"
#import "ALContainerScanViewController.h"
#import "ALVerticalContainerScanViewController.h"
+#import "ALParallelMeterWithJSONScanViewController.h"
+
@interface ALOthersExampleManager ()
@@ -67,10 +69,10 @@ - (void)initExampleData {
ALExample *voucherCodeScanning = [[ALExample alloc] initWithName:NSLocalizedString(@"Voucher Code", nil)
image:[UIImage imageNamed:@"voucher"]
viewController:[ALVoucherCodeScanViewController class]];
-
+
ALExample *documentScanner = [[ALExample alloc] initWithName:NSLocalizedString(@"Document Scanner", nil)
- image:[UIImage imageNamed:@"document"]
- viewController:[ALDocumentScanViewController class]];
+ image:[UIImage imageNamed:@"document"]
+ viewController:[ALDocumentScanViewController class]];
ALExample *scrabbleScanning = [[ALExample alloc] initWithName:NSLocalizedString(@"Scrabble Anagram", nil)
image:[UIImage imageNamed:@"scrabble"]
@@ -88,11 +90,15 @@ - (void)initExampleData {
image:[UIImage imageNamed:@"cow-tag"]
viewController:[ALCattleTagScanViewController class]];
+ ALExample *parallelScanning = [[ALExample alloc] initWithName:NSLocalizedString(@"Parallel Scanning (Meter + Barcode)", nil)
+ image:[UIImage imageNamed:@"parallel-scanning"]
+ viewController:[ALParallelMeterWithJSONScanViewController class]];
+
self.sectionNames = @[@"Others",];
self.examples = @{
- self.sectionNames[0] : @[serialNumberScanning, containerScanning, verticalContainerScanning, cattleTagScanning, ibanScanning, rbScanning, voucherCodeScanning, scrabbleScanning, recordScanning, isbnScanning, documentScanner],
- };
+ self.sectionNames[0] : @[serialNumberScanning, containerScanning, verticalContainerScanning, cattleTagScanning, ibanScanning, rbScanning, voucherCodeScanning, scrabbleScanning, recordScanning, isbnScanning, documentScanner, parallelScanning],
+ };
}
@end
diff --git a/AnylineExamples/Anyline Demo App/Info.plist b/AnylineExamples/Anyline Demo App/Info.plist
index 1555954bd..cdefa95ed 100755
--- a/AnylineExamples/Anyline Demo App/Info.plist
+++ b/AnylineExamples/Anyline Demo App/Info.plist
@@ -17,7 +17,7 @@
CFBundlePackageType
APPL
CFBundleShortVersionString
- 39.0.0
+ 41.0.0-preview.1
CFBundleSignature
????
CFBundleVersion
diff --git a/AnylineExamples/Anyline Examples Source/Barcode/ViewController/ALMultiformatBarcodeScanViewController.m b/AnylineExamples/Anyline Examples Source/Barcode/ViewController/ALMultiformatBarcodeScanViewController.m
index 8d11318fb..c78ef500e 100755
--- a/AnylineExamples/Anyline Examples Source/Barcode/ViewController/ALMultiformatBarcodeScanViewController.m
+++ b/AnylineExamples/Anyline Examples Source/Barcode/ViewController/ALMultiformatBarcodeScanViewController.m
@@ -69,11 +69,6 @@ - (void)viewDidLoad {
config.scanFeedbackConfig.blinkAnimationOnResult = NO;
config.scanFeedbackConfig.beepOnResult = NO;
config.scanFeedbackConfig.strokeWidth = 3;
- config.cutoutConfig.path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, frame.size.width, frame.size.height)];
- config.cutoutConfig.maxPercentWidth = 1;
- config.cutoutConfig.maxPercentHeight = 1;
- config.cutoutConfig.widthPercent = 1;
- config.cutoutConfig.strokeColor = [UIColor clearColor];
config.cutoutConfig.feedbackStrokeColor = [UIColor clearColor];
config.cutoutConfig.usesAnimatedRect = YES;
@@ -170,11 +165,6 @@ - (void)viewDidLoad {
scanButton.alpha = 0;
self.scanButton = scanButton;
- ALRoundedView * feedback = [[ALRoundedView alloc] initWithFrame:CGRectMake(20, frame.size.height/3, frame.size.width - 40, frame.size.height/3)];
- feedback.borderColor = [UIColor colorWithWhite:1 alpha:0.8];
- feedback.borderWidth = 2;
- feedback.cornerRadius = 15;
- [self.scanView addSubview:feedback];
}
#pragma mark - IBAction methods
diff --git a/AnylineExamples/Anyline Examples Source/CompositeScanning/ALParallelMeterWithJSONScanViewController.h b/AnylineExamples/Anyline Examples Source/CompositeScanning/ALParallelMeterWithJSONScanViewController.h
new file mode 100644
index 000000000..a03451fb4
--- /dev/null
+++ b/AnylineExamples/Anyline Examples Source/CompositeScanning/ALParallelMeterWithJSONScanViewController.h
@@ -0,0 +1,9 @@
+#import "ALBaseScanViewController.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface ALParallelMeterWithJSONScanViewController : ALBaseScanViewController
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/AnylineExamples/Anyline Examples Source/CompositeScanning/ALParallelMeterWithJSONScanViewController.m b/AnylineExamples/Anyline Examples Source/CompositeScanning/ALParallelMeterWithJSONScanViewController.m
new file mode 100644
index 000000000..17b5cef75
--- /dev/null
+++ b/AnylineExamples/Anyline Examples Source/CompositeScanning/ALParallelMeterWithJSONScanViewController.m
@@ -0,0 +1,208 @@
+#import "ALParallelMeterWithJSONScanViewController.h"
+#import "UIViewController+ALExamplesAdditions.h"
+
+const bool parallel_scan_view_uses_json_config_for_setup = true;
+NSString * const parallel_scan_plugin_config_json_filename = @"meter_barcode_parallel"; // without the .json extension
+
+@interface ALParallelMeterWithJSONScanViewController ()
+
+@property (nonatomic, strong) ALMeterScanViewPlugin *meterScanViewPlugin;
+
+@property (nonatomic, strong) ALBarcodeScanViewPlugin *barcodeScanViewPlugin;
+
+@property (nonatomic, strong) ALParallelScanViewPluginComposite *parallelScanViewPlugin;
+
+@property (nonatomic, strong) ALScanView *scanView;
+
+@end
+
+
+@implementation ALParallelMeterWithJSONScanViewController
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ self.title = @"Parallel Meter and Barcode Scanning";
+ [self setupAndStartPlugins];
+}
+
+- (void)setupAndStartPlugins {
+
+ if (parallel_scan_view_uses_json_config_for_setup) {
+ [self setupPluginsWithJSON];
+ } else {
+ [self setupPluginsWithManually];
+ }
+
+ NSAssert(self.parallelScanViewPlugin, @"parallelScanViewPlugin was not set up properly!");
+
+ self.scanView = [[ALScanView alloc] initWithFrame:[self scanViewFrame]
+ scanViewPlugin:self.parallelScanViewPlugin];
+
+ [self.view addSubview:self.scanView];
+
+ [self.scanView startCamera];
+
+ [self.parallelScanViewPlugin startAndReturnError:nil];
+}
+
+- (void)setupPluginsWithJSON {
+
+ NSError *error = nil;
+
+ // NOTE: we made an assumption here that the JSON is an appropriately-defined config of
+ // a parallel scan view with two members: a barcode scan plugin and a meter scan plugin.
+
+ self.parallelScanViewPlugin = (ALParallelScanViewPluginComposite *)[ALAbstractScanViewPluginComposite
+ scanViewPluginForConfigDict:self.configDict
+ delegate:self
+ error:&error];
+
+ for (ALAbstractScanViewPlugin *scanPlugin in self.parallelScanViewPlugin.childPlugins) {
+ if ([scanPlugin isKindOfClass:ALBarcodeScanViewPlugin.class]) {
+ self.barcodeScanViewPlugin = (ALBarcodeScanViewPlugin *)scanPlugin;
+ } else if ([scanPlugin isKindOfClass:ALMeterScanViewPlugin.class]) {
+ self.meterScanViewPlugin = (ALMeterScanViewPlugin *)scanPlugin;
+ }
+ }
+
+ // (Optional) If desired, you may set scan delegates for individual scan view plugins,
+ // allowing you to read scan results individually as they detected:
+ NSAssert(self.barcodeScanViewPlugin != nil, @"barcodeScanViewPlugin should not be nil");
+ NSAssert(self.meterScanViewPlugin != nil, @"meterScanViewPlugin should not be nil");
+
+ [self.barcodeScanViewPlugin.barcodeScanPlugin addDelegate:self];
+ [self.meterScanViewPlugin.meterScanPlugin addDelegate:self];
+
+}
+
+- (void)setupPluginsWithManually {
+
+ // you can set up the parallel scan without a JSON config file, if you wish.
+ NSError *error = nil;
+
+ // Meter Plugin
+ ALMeterScanPlugin *meterScanPlugin = [[ALMeterScanPlugin alloc] initWithPluginID:@"METER"
+ delegate:self
+ error:&error];
+ self.meterScanViewPlugin = [[ALMeterScanViewPlugin alloc] initWithScanPlugin:meterScanPlugin];
+
+ // Barcode Plugin
+ ALBarcodeScanPlugin *barcodeScanPlugin = [[ALBarcodeScanPlugin alloc] initWithPluginID:@"BARCODE"
+ delegate:self
+ error:&error];
+ [barcodeScanPlugin setBarcodeFormatOptions:@[ kCodeTypeAll ]];
+ self.barcodeScanViewPlugin = [[ALBarcodeScanViewPlugin alloc]
+ initWithScanPlugin:barcodeScanPlugin];
+
+ // Parallel Scan View Plugin
+ self.parallelScanViewPlugin = [[ALParallelScanViewPluginComposite alloc]
+ initWithPluginID:@"Energy and Meter Parallel"];
+
+ // (Optional) - make certain child plugins return without a scan result after a timeout
+ //
+ // A timeout delay determines how long the parallel plugin waits for any "optional"
+ // child plugins to be scanned, before ignoring them. After all non-optional child plugins
+ // have already been scanned, the parallel scan plugin waits for an extra, predetermined
+ // time period (the so-called timeout delay), and then returns with all the results gathered
+ // up to that point through its delegate. NOTE: To use it, at least one child plugin must
+ // have been marked as optional when adding to it. Otherwise all child plugins are waited
+ // on before the delegate callback is invoked.
+
+ // When not explicitly set, the default delay is 3.0 seconds.
+ self.parallelScanViewPlugin.optionalTimeoutDelay = @3.5;
+
+ // You can make a member ScanViewPlugin (in this case, for the barcode) by setting its
+ // isOptional property to YES. (NOTE: make sure to set this BEFORE it is added to the
+ // parallel plugin.)
+ self.barcodeScanViewPlugin.isOptional = YES;
+
+ // Add the component plugins.
+ [self.parallelScanViewPlugin addPlugin:self.meterScanViewPlugin];
+ [self.parallelScanViewPlugin addPlugin:self.barcodeScanViewPlugin];
+
+ // make oneself a ALCompositeScanPluginDelegate (for the aggregated results)
+ [self.parallelScanViewPlugin addDelegate:self];
+}
+
+- (void)displayResults:(NSString *)resultsMsg {
+ UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Results"
+ message:resultsMsg
+ preferredStyle:UIAlertControllerStyleAlert];
+ __weak __block typeof(self) weakSelf = self;
+ [alertController addAction:[UIAlertAction actionWithTitle:@"OK"
+ style:UIAlertActionStyleDefault
+ handler:^(UIAlertAction * _Nonnull action) {
+
+ [weakSelf.parallelScanViewPlugin startAndReturnError:nil];
+ }]];
+
+ [self.navigationController presentViewController:alertController animated:YES completion:nil];
+}
+
+- (NSDictionary * _Nonnull)configDict {
+ // read the JSON config file
+ NSString *jsonFilePath = [[NSBundle mainBundle] pathForResource:parallel_scan_plugin_config_json_filename
+ ofType:@"json"];
+ NSData *data = [NSData dataWithContentsOfFile:jsonFilePath];
+
+ NSError *error = nil;
+ NSDictionary *configDict = [NSJSONSerialization JSONObjectWithData:data
+ options:NSJSONReadingMutableContainers
+ error:&error];
+ NSAssert(configDict != nil, @"unable to read configuration JSON file!");
+ return configDict;
+}
+
+// MARK: - ALCompositeScanPluginDelegate
+
+- (void)anylineCompositeScanPlugin:(ALAbstractScanViewPluginComposite * _Nonnull)anylineCompositeScanPlugin
+ didFindResult:(ALCompositeResult * _Nonnull)scanResult {
+
+ // this method is executed when all 'required' component plugins have
+ // been scanned.
+
+ NSMutableArray *resultStrs = [NSMutableArray arrayWithCapacity:2];
+ for (NSString *key in scanResult.result.allKeys) {
+ id res = scanResult.result[key];
+ if ([res isKindOfClass:ALMeterResult.class]) {
+ [resultStrs addObject:
+ [NSString stringWithFormat:@"meter result: %@",
+ [(ALMeterResult *)res result]]
+ ];
+ } else if ([res isKindOfClass:ALBarcodeResult.class]) {
+ [resultStrs addObject:
+ [NSString stringWithFormat:@"barcode result: %@",
+ [(ALBarcodeResult *)res result].firstObject.value]
+ ];
+ }
+ }
+ NSString *message = [resultStrs componentsJoinedByString:@" | "];
+ NSLog(@"Parallel Scan: aggregate result: %@", message);
+ [self displayResults:message];
+}
+
+// MARK: - ALBarcodeScanPluginDelegate
+
+- (void)anylineBarcodeScanPlugin:(ALBarcodeScanPlugin * _Nonnull)anylineBarcodeScanPlugin
+ didFindResult:(ALBarcodeResult * _Nonnull)scanResult {
+ NSString *barcodeResultStr = [[scanResult.result firstObject] value];
+
+ // by setting a ALBarcodeScanPluginDelegate you can detect a barcode scan before the
+ // composite (parallel) plugin delegate is called.
+ NSLog(@"Parallel Scan: barcode result: %@", barcodeResultStr);
+}
+
+
+// MARK: - ALMeterScanPluginDelegate
+
+- (void)anylineMeterScanPlugin:(ALMeterScanPlugin * _Nonnull)anylineMeterScanPlugin
+ didFindResult:(ALMeterResult * _Nonnull)scanResult {
+
+ // by setting a ALMeterScanPluginDelegate you can detect a meter scan before the
+ // composite (parallel) plugin delegate is called.
+ NSString *meterResultStr = scanResult.result;
+ NSLog(@"Parallel Scan: meter result: %@", meterResultStr);
+}
+
+@end
diff --git a/AnylineExamples/Anyline Examples Source/CompositeScanning/meter_barcode_parallel.json b/AnylineExamples/Anyline Examples Source/CompositeScanning/meter_barcode_parallel.json
new file mode 100644
index 000000000..4ac06d453
--- /dev/null
+++ b/AnylineExamples/Anyline Examples Source/CompositeScanning/meter_barcode_parallel.json
@@ -0,0 +1,86 @@
+{
+ "parallelViewPluginComposite": {
+ "id": "meter_barcode_parallel_scan",
+ "cancelOnResult": true,
+ "viewPlugins": [
+ {
+ "viewPlugin": {
+ "plugin": {
+ "id": "METER",
+ "meterPlugin": {
+ "scanMode": "AUTO_ANALOG_DIGITAL_METER"
+ }
+ },
+ "cutoutConfig": {
+ "style": "rect",
+ "width": 768,
+ "alignment": "top_half",
+ "maxWidthPercent": "100%",
+ "strokeWidth": 2,
+ "strokeColor": "FF0000",
+ "cornerRadius": 4,
+ "outerColor": "000000",
+ "outerAlpha": 0.5,
+ "feedbackStrokeColor": "0099FF",
+ "offset": {
+ "x": 0,
+ "y": 20
+ }
+ },
+ "scanFeedback": {
+ "style": "CONTOUR_RECT",
+ "strokeColor": "FFFFFF",
+ "strokeWidth": 2,
+ "fillColor": "220099FF",
+ "cornerRadius": 2,
+ "redrawTimeout": 200,
+ "animationDuration": 75,
+ "blinkOnResult": true,
+ "beepOnResult": true,
+ "vibrateOnResult": true
+ },
+ "cancelOnResult": true
+ }
+ },
+ {
+ "viewPlugin": {
+ "plugin" : {
+ "id" : "BARCODE",
+ "barcodePlugin" : {
+ "barcodeFormatOptions" : ["CODE_128"]
+ }
+ },
+ "cutoutConfig": {
+ "style": "rect",
+ "width": 512,
+ "alignment": "center",
+ "maxWidthPercent": "100%",
+ "ratioFromSize": {
+ "width": 3,
+ "height": 1
+ },
+ "strokeWidth": 2,
+ "cornerRadius": 2,
+ "strokeColor": "FFFFFF",
+ "outerColor": "000000",
+ "outerAlpha": 0.75,
+ "feedbackStrokeColor": "0099FF",
+ "offset": {
+ "x": 0,
+ "y": -60
+ }
+ },
+ "scanFeedback": {
+ "style": "contour_rect",
+ "strokeColor": "0099FF",
+ "fillColor": "220099FF",
+ "beepOnResult": true,
+ "vibrateOnResult": true,
+ "blinkAnimationOnResult": true
+ },
+ "cancelOnResult": true
+ }
+ }
+ ]
+ }
+}
diff --git a/AnylineExamples/Anyline Examples Source/SerialNumber/ViewController/ALUniversalSerialNumberScanViewController.m b/AnylineExamples/Anyline Examples Source/SerialNumber/ViewController/ALUniversalSerialNumberScanViewController.m
index e1b0aaad6..da16db26b 100644
--- a/AnylineExamples/Anyline Examples Source/SerialNumber/ViewController/ALUniversalSerialNumberScanViewController.m
+++ b/AnylineExamples/Anyline Examples Source/SerialNumber/ViewController/ALUniversalSerialNumberScanViewController.m
@@ -31,7 +31,7 @@ @implementation ALUniversalSerialNumberScanViewController
- (void)viewDidLoad {
[super viewDidLoad];
- self.title = @"Universal Serial Number";
+ self.title = @"Meter Serial Number";
// Initializing the scan view. It's a UIView subclass. We set the frame to fill the whole screen
CGRect frame = [self scanViewFrame];
@@ -139,7 +139,7 @@ - (void)anylineOCRScanPlugin:(ALOCRScanPlugin *)anylineOCRScanPlugin
didFindResult:(ALOCRResult *)result {
// We are done. Cancel scanning
NSMutableArray *resultData = [[NSMutableArray alloc] init];
- [resultData addObject:[[ALResultEntry alloc] initWithTitle:@"Universal Serial Number" value:result.result shouldSpellOutValue:YES]];
+ [resultData addObject:[[ALResultEntry alloc] initWithTitle:@"Meter Serial Number" value:result.result shouldSpellOutValue:YES]];
NSString *jsonString = [self jsonStringFromResultData:resultData];
__weak __block typeof(self) weakSelf = self;
diff --git a/AnylineExamples/Anyline Examples Source/TIN/ViewController/ALTINScanViewController.m b/AnylineExamples/Anyline Examples Source/TIN/ViewController/ALTINScanViewController.m
index d915190de..04cb38155 100644
--- a/AnylineExamples/Anyline Examples Source/TIN/ViewController/ALTINScanViewController.m
+++ b/AnylineExamples/Anyline Examples Source/TIN/ViewController/ALTINScanViewController.m
@@ -22,8 +22,6 @@ @interface ALTINScanViewController ()
+#import "UIFont+ALExamplesAdditions.h"
+#import "UIColor+ALExamplesAdditions.h"
+#import "AppDelegate.h"
@import CoreMotion;
@@ -67,6 +70,12 @@ - (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
self.startTime = CACurrentMediaTime();
+ [self enableLandscapeOrientation:self.isOrientationFlipped];
+}
+
+- (void)viewWillDisappear:(BOOL)animated {
+ [super viewWillDisappear:animated];
+ [self enableLandscapeOrientation:NO];
}
- (NSString *)jsonStringFromResultData:(NSArray*)resultData {
@@ -234,6 +243,69 @@ - (CGRect)scanViewFrame {
frame.size.width, frame.size.height - navbarHeight);
}
+#pragma mark - FlipOrietation
+
+- (void)flipOrientationPressed:(id)sender {
+ self.isOrientationFlipped = !self.isOrientationFlipped;
+ [self enableLandscapeOrientation:self.isOrientationFlipped];
+}
+
+- (void)enableLandscapeOrientation:(BOOL)isLandscape {
+ [self enableLandscapeRight:isLandscape];
+
+ NSNumber *value;
+ if (isLandscape) {
+ value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
+ } else {
+ value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
+ }
+
+ [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
+ [UIViewController attemptRotationToDeviceOrientation];
+}
+
+- (BOOL)shouldAutorotate {
+ return NO;
+}
+
+- (void)enableLandscapeRight:(BOOL)enable {
+ AppDelegate* appDelegate = (AppDelegate*)[[UIApplication sharedApplication]delegate];
+ appDelegate.enableLandscapeRight = enable;
+}
+
+- (void)setupFlipOrientationButton {
+ self.flipOrientationButton = [UIButton buttonWithType:UIButtonTypeCustom];
+ [self.flipOrientationButton addTarget:self
+ action:@selector(flipOrientationPressed:)
+ forControlEvents:UIControlEventTouchUpInside];
+
+ self.flipOrientationButton.frame = CGRectMake(0, 0, 220, 50);
+ UIImage *buttonImage = [UIImage imageNamed:@"baseline_screen_rotation_white_24pt"];
+ [self.flipOrientationButton setImage:buttonImage forState:UIControlStateNormal];
+ self.flipOrientationButton.imageView.tintColor = UIColor.whiteColor;
+ [self.flipOrientationButton setImageEdgeInsets:UIEdgeInsetsMake(0.0, 0.0, 0.0, 10.0)];
+ self.flipOrientationButton.imageView.contentMode = UIViewContentModeScaleAspectFill;
+ self.flipOrientationButton.adjustsImageWhenDisabled = NO;
+
+ [self.flipOrientationButton setTitleEdgeInsets:UIEdgeInsetsMake(0, 5.0, 0.0, 5.0)];
+ [self.flipOrientationButton setTitle:@"Change Screen Orientation" forState:UIControlStateNormal];
+ self.flipOrientationButton.titleLabel.font = [UIFont AL_proximaRegularWithSize:14];
+
+ [self.flipOrientationButton setTranslatesAutoresizingMaskIntoConstraints:NO];
+ [self.view addSubview:self.flipOrientationButton];
+ self.flipOrientationButton.layer.cornerRadius = 3;
+ self.flipOrientationButton.backgroundColor = [[UIColor AL_examplesBlue] colorWithAlphaComponent:0.85];
+ self.isOrientationFlipped = false;
+
+ NSArray *flipCosntraints = @[[self.flipOrientationButton.widthAnchor constraintEqualToConstant:220],
+ [self.flipOrientationButton.heightAnchor constraintEqualToConstant:50],
+ [self.flipOrientationButton.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor constant:-20],
+ [self.flipOrientationButton.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor constant:0]];
+
+ [self.view addConstraints:flipCosntraints];
+ [NSLayoutConstraint activateConstraints:flipCosntraints];
+}
+
#pragma mark - NSKeyValueObserving
- (void)observeValueForKeyPath:(NSString *)keyPath
diff --git a/AnylineExamples/AnylineExamples.xcodeproj/project.pbxproj b/AnylineExamples/AnylineExamples.xcodeproj/project.pbxproj
index 933154a1e..c94b5a053 100644
--- a/AnylineExamples/AnylineExamples.xcodeproj/project.pbxproj
+++ b/AnylineExamples/AnylineExamples.xcodeproj/project.pbxproj
@@ -49,6 +49,7 @@
29D8242790C62F87231582E6 /* ALLicensePlateResultOverlayView.m in Sources */ = {isa = PBXBuildFile; fileRef = 13881BADEC0C6D4F757DEC90 /* ALLicensePlateResultOverlayView.m */; };
2D1EC37BF43B70AA6016824D /* CustomerSelfReadingConfirmationViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = E539A0891F231A43F3A7089A /* CustomerSelfReadingConfirmationViewController.xib */; };
2FEAFACDC392E8898C3C97BD /* ALRoundedView.m in Sources */ = {isa = PBXBuildFile; fileRef = A15FCC2BD1A9E95397F7F99F /* ALRoundedView.m */; };
+ 30F4F4027665E6F24DC48EC5 /* ALParallelMeterWithJSONScanViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9990A51CA256F52B88A59AE0 /* ALParallelMeterWithJSONScanViewController.m */; };
332E5FE5513F6CDD2346D6D2 /* ALUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = BBEF6BE85BA00F9E1011D1E1 /* ALUtils.m */; };
37B2D510A28CED75400D97AF /* ALExampleManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B7F93940133379A464B2ECA1 /* ALExampleManager.m */; };
37B8BA82610E2579475245FC /* ALNFCScanViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D76DB0B1EDA3DEE5553F4D2 /* ALNFCScanViewController.m */; };
@@ -108,6 +109,7 @@
83C2E2BFA23265B9E254A1D1 /* ALBaseScanViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 49A507ABFDFAE4C3298D842D /* ALBaseScanViewController.m */; };
841B7C06D4FA85F6D334580C /* ALISBNHeaderCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 7474A92ECB1EC93FFE2A523F /* ALISBNHeaderCell.m */; };
8543A04986941842302938D1 /* UIView+ALExamplesAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 7A8B3E959502E4A04A0D95FF /* UIView+ALExamplesAdditions.m */; };
+ 860F95A49274210ADE787DA0 /* meter_barcode_parallel.json in Resources */ = {isa = PBXBuildFile; fileRef = F84B123B1654CB102F551D25 /* meter_barcode_parallel.json */; };
8678F0EF3FACD7EB8A9AAE26 /* ReadingTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 254FBCFC83BBCE0B37B8CD99 /* ReadingTableViewCell.xib */; };
86E32185F510312CB5C33314 /* CustomerSelfReading.m in Sources */ = {isa = PBXBuildFile; fileRef = C401B4BF009D1D8E2BED8173 /* CustomerSelfReading.m */; };
87CCC52F9F8B0CFEE789DAFF /* NSAttributedString+ALExamplesAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 54C6C24B452735E53395244B /* NSAttributedString+ALExamplesAdditions.m */; };
@@ -400,6 +402,7 @@
987864E0F8E8E2F22C729406 /* CustomerSelfReading.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CustomerSelfReading.h; sourceTree = ""; };
993E94F5B4D905C28394B2AD /* UIViewController+ALExamplesAdditions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+ALExamplesAdditions.m"; sourceTree = ""; };
997B2A1F82805B0685BBA76E /* ALIBANScanViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ALIBANScanViewController.m; sourceTree = ""; };
+ 9990A51CA256F52B88A59AE0 /* ALParallelMeterWithJSONScanViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ALParallelMeterWithJSONScanViewController.m; sourceTree = ""; };
9A230B5C8B947BEC3F18730B /* ALMeter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ALMeter.h; sourceTree = ""; };
9A5A0B8B16A226B0EAC39924 /* serial_number_view_config.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = serial_number_view_config.json; sourceTree = ""; };
9B2C52A1458BA3161852471B /* ALMeterExampleManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ALMeterExampleManager.h; sourceTree = ""; };
@@ -440,6 +443,7 @@
B1866752D7457CFD00F2BB10 /* NSManagedObject+ALExamplesAdditions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSManagedObject+ALExamplesAdditions.m"; sourceTree = ""; };
B1D774A5ADDF5C4E7628C04F /* ALLicensePlateExampleManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ALLicensePlateExampleManager.h; sourceTree = ""; };
B2609040C0044ED642B23323 /* ALMeterSerialNumberScanViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ALMeterSerialNumberScanViewController.m; sourceTree = ""; };
+ B47BD6FE89D95F7402CF807D /* ALParallelMeterWithJSONScanViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ALParallelMeterWithJSONScanViewController.h; sourceTree = ""; };
B796B03399AA17084BF87FE2 /* ALIntroHelpView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ALIntroHelpView.h; sourceTree = ""; };
B7B4776BB82FA4F7729784D0 /* ALExample.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ALExample.m; sourceTree = ""; };
B7F93940133379A464B2ECA1 /* ALExampleManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ALExampleManager.m; sourceTree = ""; };
@@ -525,6 +529,7 @@
F7151F89C55A657556691214 /* ScanHistory+CoreDataProperties.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ScanHistory+CoreDataProperties.h"; sourceTree = ""; };
F72E21F38E68BE8268DA8B75 /* ALVoucherCodeScanViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ALVoucherCodeScanViewController.h; sourceTree = ""; };
F79688067905522060BCFE75 /* ALHeaderCollectionReusableView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ALHeaderCollectionReusableView.m; sourceTree = ""; };
+ F84B123B1654CB102F551D25 /* meter_barcode_parallel.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = meter_barcode_parallel.json; sourceTree = ""; };
F8F473BAEC7288A2E304C228 /* ScanHistoryMigration3to4.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ScanHistoryMigration3to4.h; sourceTree = ""; };
F92107DB6698B83180CD5864 /* CustomerDataViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CustomerDataViewController.m; sourceTree = ""; };
FDCEFD699881115D834BAA3A /* ALDeviceInformationHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ALDeviceInformationHelper.m; sourceTree = ""; };
@@ -810,6 +815,7 @@
0773AADFFF89D2B32D9D4BEA /* MeterImagesAssets.xcassets */,
130C58F489D374A154DB76C2 /* Barcode */,
920FC7041BC75E7BC7B66293 /* CattleTag */,
+ FE110D9D8770D6DC4767AC0C /* CompositeScanning */,
FDBF785D090EB8336A7FD16D /* ContainerScannerHorizontal */,
0D9835CFDE0CC62A1A02D0DF /* ContainerScannerVertical */,
5829676095E89FA2B57CAD0E /* CoreData */,
@@ -1410,6 +1416,16 @@
path = ContainerScannerHorizontal;
sourceTree = "";
};
+ FE110D9D8770D6DC4767AC0C /* CompositeScanning */ = {
+ isa = PBXGroup;
+ children = (
+ B47BD6FE89D95F7402CF807D /* ALParallelMeterWithJSONScanViewController.h */,
+ 9990A51CA256F52B88A59AE0 /* ALParallelMeterWithJSONScanViewController.m */,
+ F84B123B1654CB102F551D25 /* meter_barcode_parallel.json */,
+ );
+ path = CompositeScanning;
+ sourceTree = "";
+ };
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -1490,6 +1506,7 @@
194E973F43A3B0B57A330BB5 /* energyMockData2.json in Resources */,
406E5D4689D2162E66631DCF /* iban_config.json in Resources */,
DED860F64AF49DD872DCAC2C /* isbn_config.json in Resources */,
+ 860F95A49274210ADE787DA0 /* meter_barcode_parallel.json in Resources */,
126C1E99EAA1D1E63FAB2CCE /* meter_barcode_view_config.json in Resources */,
EFCF9293DCE54B0BB32ED198 /* rb_config.json in Resources */,
BF5534687932FF0FBC0742BB /* record_number_config.json in Resources */,
@@ -1573,6 +1590,7 @@
4FFCDDFFE82E17F6D6C38CCE /* ALOthersExampleManager.m in Sources */,
7B974FABA902C5631FDD2681 /* ALPDF417ScanViewController.m in Sources */,
A9B86F7EC70516E6742E48BA /* ALParallelMeterScanViewController.m in Sources */,
+ 30F4F4027665E6F24DC48EC5 /* ALParallelMeterWithJSONScanViewController.m in Sources */,
E2B5A3C0DD9F2F95F8DBD47A /* ALPrivacyForwardingViewController.m in Sources */,
74BDDA1262C89D83FE54EECB /* ALPrivacyViewController.m in Sources */,
21A22328A97C63E67AE854BA /* ALProductExampleManager.m in Sources */,
diff --git a/AnylineExamples/AnylineExamples.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/AnylineExamples/AnylineExamples.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
deleted file mode 100644
index 18d981003..000000000
--- a/AnylineExamples/AnylineExamples.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
- IDEDidComputeMac32BitWarning
-
-
-
diff --git a/Documentation/html/Blocks/ALImageProviderBlock.html b/Documentation/html/Blocks/ALImageProviderBlock.html
index 02f02f26a..313dc5359 100644
--- a/Documentation/html/Blocks/ALImageProviderBlock.html
+++ b/Documentation/html/Blocks/ALImageProviderBlock.html
@@ -112,7 +112,7 @@ Declared In