Skip to content

Commit

Permalink
Version 1.1
Browse files Browse the repository at this point in the history
Bug Fixes, Performance Improvements, Documentation Updates
  • Loading branch information
iRare Media committed Dec 21, 2013
1 parent 95edbfc commit 38d9ec1
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 7 deletions.
123 changes: 121 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,123 @@
UIScannerView
=============
<img width=725 src="https://raw.github.com/iRareMedia/UIScannerView/ScanBanner.png"/>

Simple barcode scanner UIView subclass for iOS apps. Quickly and efficiently scans a large variety of barcodes using the iOS device's built in camera.

UIScannerView is a UIView subclass for scanning barcodes in iOS applications. UIScannerView uses advanced barcode scanning built specifically for iOS. Scan both 2D and 1D barcodes such as PDF417, QR, Aztec, EAN, UPC, Code 128, etc. Get a barcode scanner up and running in your iOS app in only a few minutes.

If you like the project, please [star it](https://github.com/iRareMedia/UIScannerView) on GitHub! Watch the project on GitHub for updates. If you use UIScannerView in your app, send an email to contact@iraremedia.com or let us know on Twitter @iRareMedia.

# Project Features
UIScannerView is a great way to integrate barcode scanning in your iOS app. Below are a few key project features and highlights.
* Scan Aztec, Code 128, Code 39, Code 39 Mod 43, Code 93, EAN13, EAN8, PDF417, QR, and UPCE codes.
* Use the iOS device's native hardware / camera and corresponding AVFoundation classes
* Supports tap-to-focus, auto focus, and various other AVCaptureSession features
* Setup only takes a few minutes and can be done almost entirely in interface files
* Access in-depth documentation, code comments, and verbose logging
* Delegate methods, properties, and methods give you complete control over your scan
* iOS Sample-app demonstrates how to quickly and easily setup a UIScannerView
* Frequent updates to the project based on user issues and requests
* Easily contribute to the project

# Project Information
Learn more about the project requirements, licensing, and contributions.

## Requirements
Requires Xcode 5.0.1 for use in any iOS Project. Requires a minimum of iOS 7.0 as the deployment target. Works with and is optimized for ARC and 64-bit Architecture (arm64).
* Supported build target - iOS 7.0 (Xcode 5.0.1, Apple LLVM compiler 5.0)
* Earliest supported deployment target - iOS 7.0
* Earliest compatible deployment target - iOS 7.0

NOTE: 'Supported' means that the library has been tested with this version. 'Compatible' means that the library should work on this OS version (i.e. it doesn't rely on any unavailable SDK features) but is no longer being tested for compatibility and may require tweaking or bug fixes to run correctly.

## License
You are free to make changes and use this in either personal or commercial projects. Attribution is not required, but it appreciated. A little *Thanks!* (or something to that affect) would be much appreciated. If you use UIScannerView in your app, send an email to contact@iraremedia.com or let us know on Twitter @iRareMedia. See the [full UIScannerView license here](https://github.com/iRareMedia/UIScannerView/blob/master/LICENSE.md).

## Contributions
Any contribution is more than welcome! You can contribute through pull requests and issues on GitHub. Learn more [about contributing to the project here](https://github.com/iRareMedia/UIScannerView/blob/master/CONTRIBUTING.md).

## Sample App
The iOS Sample App included with this project demonstrates how to setup and use many of the features in UIScannerView.

# Documentation
All methods, properties, types, and delegate methods available on the UIScannerView class are documented below. If you're using [Xcode 5](https://developer.apple.com/technologies/tools/whats-new.html) with UIScannerView, documentation is available directly within Xcode (just Option-Click any method for Quick Help).

## Setup
Adding UIScannerView to your project is easy. Follow these steps below to get everything up and running.

1. Add the `UIScannerView.h` and `UIScannerView.m` files into your project
2. Import where necessary, `#import "UIScannerView.h"`
3. Setup the UIScannerView when your UIViewController or view loads:

[scannerView setVerboseLogging:YES]; // Set verbose logging to YES so we can see exactly what's going on
[scannerView startCaptureSession]; // Start the capture session when the view loads - this will also start a scan session

4. Add a UIView to the corresponding / desired View Controller and set the view's custom class to `UIScannerView`
5. Subscribe to the `UIScannerView` delegate either through the interface (using the outlets inspector) or through code by subscribing to the `UIScannerViewDelegate` and then setting it.

## Sessions
UIScannerView manages barcode scanning in *sessions* which can be started or stopped at anytime. There are various session levels, each having a slightly different effect which is suitable for a different period. The **capture session** is the encompassing session which includes the stream of camera data, scan data, and any animations on the view. The **scan session** is part of the capture session. It includes only the scan data. A scan session can be stopped separate of the capture session.

## Methods
There are many methods available on UIScannerView. The most important / highlight methods are documented below. All other methods are documented in the header file and with in-code comments. You should not attempt to use methods which are not listed in the header file.

### Starting a Capture Session
Starts the current barcode scanner capture session. This method should be called when the encapsulating UIViewController is presented or is loaded, or at any appropriate time. A session will not automatically start when the UIScannerView is loaded (ex. by an interface file). Calling this method begins the AVCaptureSession and starts the collection of camera data - including scan data.

[scannerView startCaptureSession];

### Starting a Scan Session
Starts a new scanning session and keeps the same capture session (or creates a new one if none exist). This method can be called to start a new scanning session after one has been stopped (ex. automatically after a scan). This will start a new stream of scan data.

[scannerView startScanSession];

You do not need to start both a scan and capture session at the same time. They are mutually inclusive. Starting a scan session will start a capture session if one does not exist or is stopped. Starting a capture session will also start a scan session. **However**, capture sessions differ from scan sessions in that they are more of an initializer - they do extra setup work and checks that may not be necessary if one is already started.

### Stopping a Scan Session
Stops the current barcode scan. This only prevents the scan data collection. It will not stop any video feed or halt any animations. This method may be called when a scan has completed (if continuous scans are not enabled) but the scanner is still visible on screen.

[scannerView stopScanSession];

### Ending a Capture Session
Stops the current barcode scanner capture session. This causes the video feed to freeze, animations to halt, and prevents the scan data collection. This method should be called when the encapsulating UIViewController is dismissed, unloaded, or deallocated. Calling this method stops the AVCaptureSession and prevents the collection of any further camera or hardware data - including scan data. It will also remove any animations on the view.

[scannerView stopCaptureSession];

### Checking for Sessions
Check if a scan session is in progress. Returns YES if a scan session is currently in progress. NO if either a scan session or a capture session are not in progress.

BOOL isScanning = [scannerView isScanSessionInProgress];

Check if a capture session is in progress. Return YES if a capture session is currently in progress. NO a capture session is not in progress. May return YES even if a scan session is **not** in progress.

BOOL isCapturing = [scannerView isCaptureSessionInProgress];

### Parsing Scan Data
If needed, you can display the scanned barcode format to your user with this method. It converts the `codeType` object passed in the `didScanCode:onCodeType:` delegate method to a human readable barcode type name. The `codeType` is an AVMetadataObjectType string passed in the `didScanCode:onCodeType:` delegate method, or any AVMetadataObjectType barcode string. Returns a human-friendly barcode type name. May return `nil` if the barcode type is not recognized.

NSString *barcodeType = [scannerView humanReadableCodeTypeForCode:codeType];

## Delegates
The most important part of the UIScannerView is it's delegate. Information is sent to the delegate about scanned barcodes. Requests are also sent to the delegate to gather preferences and settings. Error messages may also be sent to the delegate.

### Gathering Scan Data
When a barcode is recognized and scanned, this delegate method is called. You can use this delegate method to retrieve scan information such as the barcode data and barcode type. This method may be continuously called if the `shouldEndSessionAfterFirstSuccessfulScan` delegate method returns NO.

- (void)didScanCode:(NSString *)scannedCode onCodeType:(NSString *)codeType;

### Registering for Errors
There are two types of errors that may occur when trying to setup or scan.

The first is a capture session error - a required delegate method. It is sent to the delegate when the scanner fails to properly setup the scan session. This usually occurs because it was started on a device without a camera. A possible solution would be to present the user with a prompt to manually enter the barcode text.

- (void)errorGeneratingCaptureSession:(NSError *)error;

The second is a device hardware lock error - an optional delegate method. It is sent to the delegate when the scanner cannot acquire a hardware lock in order to change configurations. This usually occurs when the user taps-to-focus. This may occur because another running application or process has a lock on the hardware configuration which prevents the scanner from focusing the camera.

- (void)errorAcquiringDeviceHardwareLock:(NSError *)error;

## Session Settings
After a barcode is scanned, the scanner must decide to continuously send data to the delegate or to stop sending information after the first successful scan. Use this delegate to specify whether data should continue to be sent or just sent once. Continuous data means that `didScanCode:onCodeType:` delegate is called repeatedly until the barcode disappears or is no longer readable.

Return YES if the scanner should stop looking for barcodes and reporting them after the first successful scan. NO if the scanner should continuously scan for barcodes. Leaving this delegate method unimplemented will result in the same action as returning YES.

- (BOOL)shouldEndSessionAfterFirstSuccessfulScan;
Binary file added ScanBanner.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 21 additions & 0 deletions Scanner App/Scanner App.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
objects = {

/* Begin PBXBuildFile section */
994BB5971865426A005F9EAE /* ScanBanner.png in Resources */ = {isa = PBXBuildFile; fileRef = 994BB5961865426A005F9EAE /* ScanBanner.png */; };
994BB59A18654271005F9EAE /* LICENSE.md in Resources */ = {isa = PBXBuildFile; fileRef = 994BB59818654271005F9EAE /* LICENSE.md */; };
994BB59B18654271005F9EAE /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 994BB59918654271005F9EAE /* README.md */; };
99A314E41850253F000917FA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 99A314E31850253F000917FA /* Foundation.framework */; };
99A314E618502540000917FA /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 99A314E518502540000917FA /* CoreGraphics.framework */; };
99A314E818502540000917FA /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 99A314E718502540000917FA /* UIKit.framework */; };
Expand All @@ -21,6 +24,9 @@
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
994BB5961865426A005F9EAE /* ScanBanner.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ScanBanner.png; path = ../../ScanBanner.png; sourceTree = "<group>"; };
994BB59818654271005F9EAE /* LICENSE.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = LICENSE.md; path = ../../LICENSE.md; sourceTree = "<group>"; };
994BB59918654271005F9EAE /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = README.md; path = ../../README.md; sourceTree = "<group>"; };
99A314E01850253F000917FA /* Scanner App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Scanner App.app"; sourceTree = BUILT_PRODUCTS_DIR; };
99A314E31850253F000917FA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
99A314E518502540000917FA /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
Expand Down Expand Up @@ -55,6 +61,14 @@
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
994BB59518654260005F9EAE /* Images */ = {
isa = PBXGroup;
children = (
994BB5961865426A005F9EAE /* ScanBanner.png */,
);
name = Images;
sourceTree = "<group>";
};
99A314D71850253F000917FA = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -102,6 +116,9 @@
99A314EA18502540000917FA /* Supporting Files */ = {
isa = PBXGroup;
children = (
994BB59518654260005F9EAE /* Images */,
994BB59818654271005F9EAE /* LICENSE.md */,
994BB59918654271005F9EAE /* README.md */,
99A314EB18502540000917FA /* Scanner App-Info.plist */,
99A314EC18502540000917FA /* InfoPlist.strings */,
99A314EF18502540000917FA /* main.m */,
Expand Down Expand Up @@ -162,6 +179,9 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
994BB59B18654271005F9EAE /* README.md in Resources */,
994BB59A18654271005F9EAE /* LICENSE.md in Resources */,
994BB5971865426A005F9EAE /* ScanBanner.png in Resources */,
99A314FC18502540000917FA /* Images.xcassets in Resources */,
99A314EE18502540000917FA /* InfoPlist.strings in Resources */,
99A314F718502540000917FA /* Main.storyboard in Resources */,
Expand Down Expand Up @@ -321,6 +341,7 @@
99A3151418502540000917FA /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
Expand Down
Binary file not shown.
6 changes: 3 additions & 3 deletions UIScannerView.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,16 @@ NS_CLASS_AVAILABLE_IOS(7_0) @interface UIScannerView : UIView <AVCaptureMetadata
@discussion This method should be called when the encapsulating UIViewController is presented or is loaded, or at any appropriate time. A session will not automatically start when the UIScannerView is loaded (ex. by an interface file). Calling this method begins the AVCaptureSession and starts the collection of camera data - including scan data. */
- (void)startCaptureSession;

/** Starts anew scanning session and keeps the same capture session (or creates a new one if none exist)
/** Starts a new scanning session and keeps the same capture session (or creates a new one if none exist)
@discussion This method can be called to start a new scanning session after one has been stopped (ex. automatically after a scan). This will start a new stream of scan data. */
- (void)startScanSession;

/** Stops the current barcode scan. This only prevents the scan data from being read. It will not stop any video feed or halt any animations.
@discussion This method should be called when a scan has completed (if continuous scans are not enabled) but the scanner is still visible on screen. */
- (void)stopScanSession;

/** Stops the current barcode scanner capture session. This causes the video feed to freeze, animations to halt, and bars the scan data from being read.
@discussion This method should be called when the encapsulating UIViewController is dismissed or is unloaded. Calling this method stops the AVCaptureSession and prevents the collection of anymore camera or hardware data - including scan data. It will also remove any animations on the view. */
/** Stops the current barcode scanner capture session. This causes the video feed to freeze, animations to halt, and prevents the scan data from being read.
@discussion This method should be called when the encapsulating UIViewController is dismissed, unloaded, or deallocated. Calling this method stops the AVCaptureSession and prevents the collection of any further camera or hardware data - including scan data. It will also remove any animations on the view. */
- (void)stopCaptureSession;

/** Converts the \p codeType passed in the \p didScanCode:onCodeType: delegate method to a human readable barcode type name
Expand Down
28 changes: 26 additions & 2 deletions UIScannerView.m
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,30 @@ - (id)initWithFrame:(CGRect)frame {
return self;
}

- (void)dealloc {
// Stop Running the Capture Session
[self.captureSession stopRunning];

// Remove all Inputs
for (AVCaptureInput *input in self.captureSession.inputs) {
[self.captureSession removeInput:input];
}

// Remove all Outputs
for (AVCaptureOutput *output in self.captureSession.outputs) {
[self.captureSession removeOutput:output];
}

// Remove preview layer
[previewLayer removeFromSuperlayer];

// Set objects to nil
self.captureSession = nil;
metadataOutput = nil;
videoInput = nil;
previewLayer = nil;
}

#pragma mark - Scanner Checks

- (BOOL)isScanSessionInProgress {
Expand Down Expand Up @@ -124,8 +148,6 @@ - (void)stopCaptureSession {

// Log the stop
if (verboseLogging) NSLog(@"[UIScannerView] Stopped capture session");

// Remove the animations
}

- (void)startScanSession {
Expand Down Expand Up @@ -179,6 +201,8 @@ - (void)setupPreviewLayer {

if (previewLayer == nil) previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.captureSession];
previewLayer.frame = self.layer.bounds;
previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
previewLayer.position = CGPointMake(CGRectGetMidX(self.layer.bounds), CGRectGetMidY(self.layer.bounds));
if ([self.layer.sublayers containsObject:previewLayer] == NO) [self.layer addSublayer:previewLayer];
}

Expand Down

0 comments on commit 38d9ec1

Please sign in to comment.