Motivation
The default scan mode provided by the Scandit Barcode Scanner searches barcodes/2d codes in the whole image. This works well when scanning individual codes. However, when scanning codes from sheets with a large number of densely packed barcodes, the full screen scan mode is not optimal as there is little control for the user to decide which code is going to get scanned. With very little code it's possible to implement mechanisms that help selecting the code to be scanned.
Two such "barcode selection modi" have been implemented in the BatchScanSample which is included in the iOS SDK.
Aim and Scan
In the first of the two modi, the camera is started with the barcode scanner in paused state. After positioning the phone such that the barcode is in the center of the image, the user presses the "Scan barcode" button to activate the barcode scanner and scan the code.
Steps
To implement the Aim and Scan mode in your application, you will need to do the following:
Enable and set the restrict active area. This will make sure that codes are only scanned in a very thin band in the center of the image.
Objective-C:
//Enable restrict area[scanSettings setActiveScanningArea:CGRectMake(0, 0.48, 1, 0.04)];Swift:
// Enable restrict areascanSettings.setActiveScanningArea(CGRect(x: 0, y: 0.48, width: 1, height: 0.04))Modify the GUI style to have a "laser" line instead of a square view finder and the scan button to the view.
Objective-C:
[self.scanditBarcodePicker.overlayController setGuiStyle:SBSGuiStyleLaser];//Add scan buttonself.scanButton = [UIButton buttonWithType:UIButtonTypeCustom];[self.scanButton setTitle:@"Scan barcode" forState:UIControlStateNormal];CGFloat red = 58/255.0, green = 194/255.0, blue = 205/255.0;[self.scanButton setBackgroundColor:[UIColor colorWithRed:red green:green blue:blue alpha:1]];self.scanButton.layer.cornerRadius = 4.0f;[self.scanButton.titleLabel setFont:[UIFont fontWithName:@"Helvetica" size:20.0]];self.scanButton.frame = CGRectMake(0, 0, 0, 0);[self.scanditBarcodePicker.overlayController.view addSubview:self.scanButton];Swift:
scanditBarcodePicker.overlayController.guiStyle = .laser// Add scan buttonscanButton = UIButton(type: .custom)scanButton.setTitle("Scan Barcode", for: .normal)scanButton.backgroundColor = UIColor(red: 55.0/255.0, green: 194.0/255.0, blue: 205.0/255.0, alpha: 1.0)scanButton.layer.cornerRadius = 4.0scanButton.frame = CGRect(x: 0, y: 0, width: 0, height: 0)scanditBarcodePicker.overlayController.view.addSubview(scanButton)Start scanning in pause state. This will initialize and open the camera but not start barcode scanning until resumeScanning (SBSBarcodePicker) is called.
Objective-C:
[self.scanditBarcodePicker startScanningInPausedState:YES];Swift:
scanditBarcodePicker.startScanning(inPausedState: true)Set action to scan button to resume scanning
Objective-C:
[self.scanButton addTarget:selfaction:@selector(startScanWithButton)forControlEvents:UIControlEventTouchUpInside];[self.scanditBarcodePicker resumeScanning];Swift:
scanButton.addTarget(self, action: #selector(startScanWithButton), for: .touchUpInside)scanditBarcodePicker.resumeScanning()Pause the scanner when a barcode is detected, show the value decoded and set the user interface to “stop mode”
Objective-C:
- (void)barcodePicker:(SBSBarcodePicker *)thePicker didScan:(SBSScanSession *)session {// call pauseScanning on the session to immediately pause scanning[session pauseScanning];SBSCode *code = [session.newlyRecognizedCodes objectAtIndex:0];// the barcodePicker:didScan delegate method is invoked from a picker-internal queue. To display// the results in the UI, you need to dispatch to the main queue. Note that it's not allowed// to use SBSScanSession in the dispatched block as it's only allowed to access the// SBSScanSession inside the barcodePicker:didScan callback. It is however safe to use results// returned by session.newlyRecognizedCodes etc.dispatch_async(dispatch_get_main_queue(), ^{NSString *symbology = code.symbologyString;NSString *barcode = code.data;UIAlertView *alert = [[UIAlertView alloc]initWithTitle:[NSString stringWithFormat:@"Scanned %@", symbology]message:barcodedelegate:selfcancelButtonTitle:@"OK"otherButtonTitles:nil];[alert show];});}Swift:
func barcodePicker(_ picker: SBSBarcodePicker, didScan session: SBSScanSession) {// call pauseScanning on the session to immediately pause scanningsession.pauseScanning()guard let code = session.newlyRecognizedCodes.first else { return }// the barcodePicker:didScan delegate method is invoked from a picker-internal queue. To display// the results in the UI, you need to dispatch to the main queue. Note that it's not allowed// to use SBSScanSession in the dispatched block as it's only allowed to access the// SBSScanSession inside the barcodePicker:didScan callback. It is however safe to use results// returned by session.newlyRecognizedCodes etc.DispatchQueue.main.async {let symbology = code.symbologyStringlet barcode = code.datalet alertController = UIAlertController(title: "Scanned \(symbology)", message: barcode, preferredStyle: .alert)alertController.addAction(UIAlertAction(title: "OK", style: .default))self.present(alertController, animated: true)}}
Scan and Confirm
In this selection mode, the camera is started and the scanner activated to scan codes. When a code is scanned a confirm dialog is shown where the user can tap confirm when the correct code has been scanned.
Steps
To implement the Scan and Confirm mode in your application, you will need to do the following:
Enable and set the restrict active area
Objective-C:
//Enable restrict area[scanSettings setActiveScanningArea:CGRectMake(0, 0.48, 1, 0.04)];Swift:
// Enable restrict areascanSettings.setActiveScanningArea(CGRect(x: 0, y: 0.48, width: 1, height: 0.04))Modify the GUI style to have a "laser" line instead of a square view finder
Objective-C:
[self.scanditBarcodePicker.overlayController setGuiStyle:SBSGuiStyleLaser];Swift:
scanditBarcodePicker.overlayController.guiStyle = .laserStart the scanning
Objective-C:
[self.scanditBarcodePicker startScanning];Swift:
scanditBarcodePicker.startScanning()Show the last barcode scanned on the screen
Objective-C:
- (void)barcodePicker:(SBSBarcodePicker*)thePicker didScan:(SBSScanSession*)session {[self.dinamLabel removeFromSuperview];CGRect screen = [[UIScreen mainScreen] bounds];NSString *barcode = code.data;NSString *symbology = code.symbologyString;NSString *text = [NSString stringWithFormat:@"%@ %@", symbology, barcode];UILabel *tmpLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 2 * screen.size.height / 3, screen.size.width, 110)];self.dinamLabel = tmpLabel;self.dinamLabel.text = text;[self.scanditBarcodePicker.overlayController.view addSubview:self.dinamLabel];}Swift:
func barcodePicker(_ picker: SBSBarcodePicker, didScan session: SBSScanSession) {guard let code = session.newlyRecognizedCodes.first else { return }dinamLabel.removeFromSuperview()let screen = UIScreen.main.boundslet text = "\(code.symbologyString) \(code.data)"DispatchQueue.main.async {let label = UILabel(frame: CGRect(x: 0, y: 2 * screen.size.height / 3, width: screen.size.width, height: 110))self.dinamLabel = labelself.dinamLabel.text = textself.scanditBarcodePicker.overlayController.view.addSubView(dinamLabel)}}