2017-11-08 10:32:33 +08:00
|
|
|
//
|
|
|
|
// Created by Matthew Smith on 11/7/17.
|
|
|
|
//
|
|
|
|
|
|
|
|
#import "BarcodeScannerViewController.h"
|
|
|
|
#import <MTBBarcodeScanner/MTBBarcodeScanner.h>
|
2018-08-12 00:17:35 +08:00
|
|
|
#import "ScannerOverlay.h"
|
2017-11-08 10:32:33 +08:00
|
|
|
|
|
|
|
|
|
|
|
@implementation BarcodeScannerViewController {
|
|
|
|
}
|
|
|
|
|
2019-12-17 03:59:07 +08:00
|
|
|
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
|
|
|
|
{
|
|
|
|
CGRect bounds = [UIScreen mainScreen].bounds;
|
|
|
|
CGRect reversedBounds = CGRectMake(bounds.origin.x, bounds.origin.y, bounds.size.height, bounds.size.width);
|
|
|
|
self.previewView.bounds = reversedBounds;
|
|
|
|
self.previewView.frame = reversedBounds;
|
|
|
|
[self.scanRect removeFromSuperview];
|
|
|
|
[self setupScanRect:reversedBounds];
|
|
|
|
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)setupScanRect:(CGRect)bounds {
|
|
|
|
self.scanRect = [[ScannerOverlay alloc] initWithFrame:bounds];
|
|
|
|
self.scanRect.translatesAutoresizingMaskIntoConstraints = NO;
|
|
|
|
self.scanRect.backgroundColor = UIColor.clearColor;
|
|
|
|
[self.view addSubview:_scanRect];
|
|
|
|
[self.view addConstraints:[NSLayoutConstraint
|
|
|
|
constraintsWithVisualFormat:@"V:[scanRect]"
|
|
|
|
options:NSLayoutFormatAlignAllBottom
|
|
|
|
metrics:nil
|
|
|
|
views:@{@"scanRect": _scanRect}]];
|
|
|
|
[self.view addConstraints:[NSLayoutConstraint
|
|
|
|
constraintsWithVisualFormat:@"H:[scanRect]"
|
|
|
|
options:NSLayoutFormatAlignAllBottom
|
|
|
|
metrics:nil
|
|
|
|
views:@{@"scanRect": _scanRect}]];
|
|
|
|
[_scanRect startAnimating];
|
|
|
|
}
|
2017-11-08 10:32:33 +08:00
|
|
|
|
|
|
|
- (void)viewDidLoad {
|
|
|
|
[super viewDidLoad];
|
|
|
|
self.previewView = [[UIView alloc] initWithFrame:self.view.bounds];
|
|
|
|
self.previewView.translatesAutoresizingMaskIntoConstraints = NO;
|
|
|
|
[self.view addSubview:_previewView];
|
|
|
|
[self.view addConstraints:[NSLayoutConstraint
|
|
|
|
constraintsWithVisualFormat:@"V:[previewView]"
|
|
|
|
options:NSLayoutFormatAlignAllBottom
|
|
|
|
metrics:nil
|
|
|
|
views:@{@"previewView": _previewView}]];
|
|
|
|
[self.view addConstraints:[NSLayoutConstraint
|
|
|
|
constraintsWithVisualFormat:@"H:[previewView]"
|
|
|
|
options:NSLayoutFormatAlignAllBottom
|
|
|
|
metrics:nil
|
|
|
|
views:@{@"previewView": _previewView}]];
|
2019-12-17 03:59:07 +08:00
|
|
|
[self setupScanRect:self.view.bounds];
|
2017-11-08 10:32:33 +08:00
|
|
|
self.scanner = [[MTBBarcodeScanner alloc] initWithPreviewView:_previewView];
|
|
|
|
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancel)];
|
2018-08-10 06:37:10 +08:00
|
|
|
[self updateFlashButton];
|
2017-11-08 10:32:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)viewDidAppear:(BOOL)animated {
|
|
|
|
[super viewDidAppear:animated];
|
|
|
|
if (self.scanner.isScanning) {
|
|
|
|
[self.scanner stopScanning];
|
|
|
|
}
|
|
|
|
[MTBBarcodeScanner requestCameraPermissionWithSuccess:^(BOOL success) {
|
|
|
|
if (success) {
|
|
|
|
[self startScan];
|
|
|
|
} else {
|
2018-01-10 23:25:40 +08:00
|
|
|
[self.delegate barcodeScannerViewController:self didFailWithErrorCode:@"PERMISSION_NOT_GRANTED"];
|
2018-01-08 21:41:49 +08:00
|
|
|
[self dismissViewControllerAnimated:NO completion:nil];
|
2017-11-08 10:32:33 +08:00
|
|
|
}
|
|
|
|
}];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)viewWillDisappear:(BOOL)animated {
|
2018-11-10 03:07:58 +08:00
|
|
|
[self.scanner stopScanning];
|
2017-11-08 10:32:33 +08:00
|
|
|
[super viewWillDisappear:animated];
|
|
|
|
if ([self isFlashOn]) {
|
|
|
|
[self toggleFlash:NO];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)startScan {
|
|
|
|
NSError *error;
|
|
|
|
[self.scanner startScanningWithResultBlock:^(NSArray<AVMetadataMachineReadableCodeObject *> *codes) {
|
|
|
|
[self.scanner stopScanning];
|
|
|
|
AVMetadataMachineReadableCodeObject *code = codes.firstObject;
|
|
|
|
if (code) {
|
|
|
|
[self.delegate barcodeScannerViewController:self didScanBarcodeWithResult:code.stringValue];
|
|
|
|
[self dismissViewControllerAnimated:NO completion:nil];
|
|
|
|
}
|
|
|
|
} error:&error];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)cancel {
|
2019-07-23 01:11:27 +08:00
|
|
|
[self.delegate barcodeScannerViewController:self didFailWithErrorCode:@"USER_CANCELED"];
|
2017-11-08 10:32:33 +08:00
|
|
|
[self dismissViewControllerAnimated:true completion:nil];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)updateFlashButton {
|
|
|
|
if (!self.hasTorch) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (self.isFlashOn) {
|
|
|
|
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Flash Off"
|
|
|
|
style:UIBarButtonItemStylePlain
|
|
|
|
target:self action:@selector(toggle)];
|
|
|
|
} else {
|
|
|
|
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Flash On"
|
|
|
|
style:UIBarButtonItemStylePlain
|
|
|
|
target:self action:@selector(toggle)];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)toggle {
|
|
|
|
[self toggleFlash:!self.isFlashOn];
|
|
|
|
[self updateFlashButton];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)isFlashOn {
|
|
|
|
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
|
|
|
|
if (device) {
|
2018-08-10 06:37:10 +08:00
|
|
|
return device.torchMode == AVCaptureFlashModeOn || device.torchMode == AVCaptureTorchModeOn;
|
2017-11-08 10:32:33 +08:00
|
|
|
}
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)hasTorch {
|
|
|
|
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
|
|
|
|
if (device) {
|
|
|
|
return device.hasTorch;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)toggleFlash:(BOOL)on {
|
|
|
|
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
|
|
|
|
if (!device) return;
|
|
|
|
|
|
|
|
NSError *err;
|
|
|
|
if (device.hasFlash && device.hasTorch) {
|
|
|
|
[device lockForConfiguration:&err];
|
|
|
|
if (err != nil) return;
|
|
|
|
if (on) {
|
|
|
|
device.flashMode = AVCaptureFlashModeOn;
|
|
|
|
device.torchMode = AVCaptureTorchModeOn;
|
|
|
|
} else {
|
|
|
|
device.flashMode = AVCaptureFlashModeOff;
|
|
|
|
device.torchMode = AVCaptureTorchModeOff;
|
|
|
|
}
|
|
|
|
[device unlockForConfiguration];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-01-08 21:41:49 +08:00
|
|
|
@end
|