diff --git a/BCScanner.xcodeproj/project.pbxproj b/BCScanner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..c60c373 --- /dev/null +++ b/BCScanner.xcodeproj/project.pbxproj @@ -0,0 +1,649 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 4C168BA717E4745000D9404D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C168BA617E4745000D9404D /* Foundation.framework */; }; + 4C168BAC17E4745100D9404D /* BCScannerViewController.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C168BAB17E4745100D9404D /* BCScannerViewController.h */; }; + 4C168BAE17E4745100D9404D /* BCScannerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C168BAD17E4745100D9404D /* BCScannerViewController.m */; }; + 4C168BB517E4745100D9404D /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C168BB417E4745100D9404D /* XCTest.framework */; }; + 4C168BB617E4745100D9404D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C168BA617E4745000D9404D /* Foundation.framework */; }; + 4C168BB817E4745100D9404D /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C168BB717E4745100D9404D /* UIKit.framework */; }; + 4C168BBB17E4745100D9404D /* libBCScanner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C168BA317E4745000D9404D /* libBCScanner.a */; }; + 4C168BC117E4745100D9404D /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 4C168BBF17E4745100D9404D /* InfoPlist.strings */; }; + 4C168BC317E4745100D9404D /* BCScannerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C168BC217E4745100D9404D /* BCScannerTests.m */; }; + 4C168BCF17E477F800D9404D /* BCVideoPreviewView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C168BCE17E477F800D9404D /* BCVideoPreviewView.m */; }; + 4C168BD517E4A30600D9404D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C168BA617E4745000D9404D /* Foundation.framework */; }; + 4C168BD717E4A30600D9404D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C168BD617E4A30600D9404D /* CoreGraphics.framework */; }; + 4C168BD817E4A30600D9404D /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C168BB717E4745100D9404D /* UIKit.framework */; }; + 4C168BDE17E4A30600D9404D /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 4C168BDC17E4A30600D9404D /* InfoPlist.strings */; }; + 4C168BE017E4A30600D9404D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C168BDF17E4A30600D9404D /* main.m */; }; + 4C168BE417E4A30600D9404D /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C168BE317E4A30600D9404D /* AppDelegate.m */; }; + 4C168BE617E4A30600D9404D /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4C168BE517E4A30600D9404D /* Images.xcassets */; }; + 4C168C0017E4A33200D9404D /* MainStoryboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4C168BFF17E4A33200D9404D /* MainStoryboard.storyboard */; }; + 4C168C0317E4A3AE00D9404D /* MainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C168C0217E4A3AE00D9404D /* MainViewController.m */; }; + 4C168C0617E4A40200D9404D /* libBCScanner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C168BA317E4745000D9404D /* libBCScanner.a */; }; + 4C168C0817E4A43F00D9404D /* BCScannerViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C168BAB17E4745100D9404D /* BCScannerViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4C168C0917E4A44200D9404D /* BCVideoPreviewView.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C168BCD17E477F800D9404D /* BCVideoPreviewView.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4C168C0B17E4A99E00D9404D /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C168C0A17E4A99E00D9404D /* AVFoundation.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 4C168BB917E4745100D9404D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C168B9B17E4745000D9404D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4C168BA217E4745000D9404D; + remoteInfo = BCSanner; + }; + 4C168C0417E4A3FE00D9404D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C168B9B17E4745000D9404D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4C168BA217E4745000D9404D; + remoteInfo = BCSanner; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 4C168BA117E4745000D9404D /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + 4C168BAC17E4745100D9404D /* BCScannerViewController.h in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 4C168BA317E4745000D9404D /* libBCScanner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libBCScanner.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C168BA617E4745000D9404D /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 4C168BAA17E4745100D9404D /* BCScanner-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "BCScanner-Prefix.pch"; sourceTree = ""; }; + 4C168BAB17E4745100D9404D /* BCScannerViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BCScannerViewController.h; sourceTree = ""; }; + 4C168BAD17E4745100D9404D /* BCScannerViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BCScannerViewController.m; sourceTree = ""; }; + 4C168BB317E4745100D9404D /* BCScannerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BCScannerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C168BB417E4745100D9404D /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; + 4C168BB717E4745100D9404D /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; + 4C168BBE17E4745100D9404D /* BCScannerTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "BCScannerTests-Info.plist"; sourceTree = ""; }; + 4C168BC017E4745100D9404D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 4C168BC217E4745100D9404D /* BCScannerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BCScannerTests.m; sourceTree = ""; }; + 4C168BCD17E477F800D9404D /* BCVideoPreviewView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BCVideoPreviewView.h; sourceTree = ""; }; + 4C168BCE17E477F800D9404D /* BCVideoPreviewView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BCVideoPreviewView.m; sourceTree = ""; }; + 4C168BD417E4A30600D9404D /* BCScannerExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BCScannerExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C168BD617E4A30600D9404D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + 4C168BDB17E4A30600D9404D /* BCScannerExample-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "BCScannerExample-Info.plist"; sourceTree = ""; }; + 4C168BDD17E4A30600D9404D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 4C168BDF17E4A30600D9404D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 4C168BE117E4A30600D9404D /* BCScannerExample-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "BCScannerExample-Prefix.pch"; sourceTree = ""; }; + 4C168BE217E4A30600D9404D /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 4C168BE317E4A30600D9404D /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 4C168BE517E4A30600D9404D /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 4C168BFF17E4A33200D9404D /* MainStoryboard.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = MainStoryboard.storyboard; sourceTree = ""; }; + 4C168C0117E4A3AE00D9404D /* MainViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MainViewController.h; sourceTree = ""; }; + 4C168C0217E4A3AE00D9404D /* MainViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MainViewController.m; sourceTree = ""; }; + 4C168C0A17E4A99E00D9404D /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4C168BA017E4745000D9404D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C168BA717E4745000D9404D /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4C168BB017E4745100D9404D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C168BB517E4745100D9404D /* XCTest.framework in Frameworks */, + 4C168BB817E4745100D9404D /* UIKit.framework in Frameworks */, + 4C168BB617E4745100D9404D /* Foundation.framework in Frameworks */, + 4C168BBB17E4745100D9404D /* libBCScanner.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4C168BD117E4A30600D9404D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C168C0B17E4A99E00D9404D /* AVFoundation.framework in Frameworks */, + 4C168C0617E4A40200D9404D /* libBCScanner.a in Frameworks */, + 4C168BD717E4A30600D9404D /* CoreGraphics.framework in Frameworks */, + 4C168BD817E4A30600D9404D /* UIKit.framework in Frameworks */, + 4C168BD517E4A30600D9404D /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 4C168B9A17E4745000D9404D = { + isa = PBXGroup; + children = ( + 4C168BA817E4745100D9404D /* BCScanner */, + 4C168BBC17E4745100D9404D /* BCSannerTests */, + 4C168BD917E4A30600D9404D /* BCScannerExample */, + 4C168BA517E4745000D9404D /* Frameworks */, + 4C168BA417E4745000D9404D /* Products */, + ); + sourceTree = ""; + }; + 4C168BA417E4745000D9404D /* Products */ = { + isa = PBXGroup; + children = ( + 4C168BA317E4745000D9404D /* libBCScanner.a */, + 4C168BB317E4745100D9404D /* BCScannerTests.xctest */, + 4C168BD417E4A30600D9404D /* BCScannerExample.app */, + ); + name = Products; + sourceTree = ""; + }; + 4C168BA517E4745000D9404D /* Frameworks */ = { + isa = PBXGroup; + children = ( + 4C168C0A17E4A99E00D9404D /* AVFoundation.framework */, + 4C168BA617E4745000D9404D /* Foundation.framework */, + 4C168BB417E4745100D9404D /* XCTest.framework */, + 4C168BB717E4745100D9404D /* UIKit.framework */, + 4C168BD617E4A30600D9404D /* CoreGraphics.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 4C168BA817E4745100D9404D /* BCScanner */ = { + isa = PBXGroup; + children = ( + 4C168BCC17E477D300D9404D /* Private */, + 4C168BAB17E4745100D9404D /* BCScannerViewController.h */, + 4C168BAD17E4745100D9404D /* BCScannerViewController.m */, + 4C168BA917E4745100D9404D /* Supporting Files */, + ); + path = BCScanner; + sourceTree = ""; + }; + 4C168BA917E4745100D9404D /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 4C168BAA17E4745100D9404D /* BCScanner-Prefix.pch */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 4C168BBC17E4745100D9404D /* BCSannerTests */ = { + isa = PBXGroup; + children = ( + 4C168BC217E4745100D9404D /* BCScannerTests.m */, + 4C168BBD17E4745100D9404D /* Supporting Files */, + ); + name = BCSannerTests; + path = BCScannerTests; + sourceTree = ""; + }; + 4C168BBD17E4745100D9404D /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 4C168BBE17E4745100D9404D /* BCScannerTests-Info.plist */, + 4C168BBF17E4745100D9404D /* InfoPlist.strings */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 4C168BCC17E477D300D9404D /* Private */ = { + isa = PBXGroup; + children = ( + 4C168BCD17E477F800D9404D /* BCVideoPreviewView.h */, + 4C168BCE17E477F800D9404D /* BCVideoPreviewView.m */, + ); + path = Private; + sourceTree = ""; + }; + 4C168BD917E4A30600D9404D /* BCScannerExample */ = { + isa = PBXGroup; + children = ( + 4C168BE217E4A30600D9404D /* AppDelegate.h */, + 4C168BE317E4A30600D9404D /* AppDelegate.m */, + 4C168C0117E4A3AE00D9404D /* MainViewController.h */, + 4C168C0217E4A3AE00D9404D /* MainViewController.m */, + 4C168BE517E4A30600D9404D /* Images.xcassets */, + 4C168BDA17E4A30600D9404D /* Supporting Files */, + ); + path = BCScannerExample; + sourceTree = ""; + }; + 4C168BDA17E4A30600D9404D /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 4C168BDB17E4A30600D9404D /* BCScannerExample-Info.plist */, + 4C168BDC17E4A30600D9404D /* InfoPlist.strings */, + 4C168BDF17E4A30600D9404D /* main.m */, + 4C168BE117E4A30600D9404D /* BCScannerExample-Prefix.pch */, + 4C168BFF17E4A33200D9404D /* MainStoryboard.storyboard */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 4C168C0717E4A43200D9404D /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C168C0817E4A43F00D9404D /* BCScannerViewController.h in Headers */, + 4C168C0917E4A44200D9404D /* BCVideoPreviewView.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 4C168BA217E4745000D9404D /* BCScanner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4C168BC617E4745100D9404D /* Build configuration list for PBXNativeTarget "BCScanner" */; + buildPhases = ( + 4C168B9F17E4745000D9404D /* Sources */, + 4C168BA017E4745000D9404D /* Frameworks */, + 4C168BA117E4745000D9404D /* CopyFiles */, + 4C168C0717E4A43200D9404D /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = BCScanner; + productName = BCSanner; + productReference = 4C168BA317E4745000D9404D /* libBCScanner.a */; + productType = "com.apple.product-type.library.static"; + }; + 4C168BB217E4745100D9404D /* BCScannerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4C168BC917E4745100D9404D /* Build configuration list for PBXNativeTarget "BCScannerTests" */; + buildPhases = ( + 4C168BAF17E4745100D9404D /* Sources */, + 4C168BB017E4745100D9404D /* Frameworks */, + 4C168BB117E4745100D9404D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 4C168BBA17E4745100D9404D /* PBXTargetDependency */, + ); + name = BCScannerTests; + productName = BCSannerTests; + productReference = 4C168BB317E4745100D9404D /* BCScannerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 4C168BD317E4A30600D9404D /* BCScannerExample */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4C168BF917E4A30600D9404D /* Build configuration list for PBXNativeTarget "BCScannerExample" */; + buildPhases = ( + 4C168BD017E4A30600D9404D /* Sources */, + 4C168BD117E4A30600D9404D /* Frameworks */, + 4C168BD217E4A30600D9404D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 4C168C0517E4A3FE00D9404D /* PBXTargetDependency */, + ); + name = BCScannerExample; + productName = BCScannerExample; + productReference = 4C168BD417E4A30600D9404D /* BCScannerExample.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4C168B9B17E4745000D9404D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0500; + ORGANIZATIONNAME = "Michael Ochs"; + TargetAttributes = { + 4C168BB217E4745100D9404D = { + TestTargetID = 4C168BD317E4A30600D9404D; + }; + }; + }; + buildConfigurationList = 4C168B9E17E4745000D9404D /* Build configuration list for PBXProject "BCScanner" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 4C168B9A17E4745000D9404D; + productRefGroup = 4C168BA417E4745000D9404D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 4C168BA217E4745000D9404D /* BCScanner */, + 4C168BB217E4745100D9404D /* BCScannerTests */, + 4C168BD317E4A30600D9404D /* BCScannerExample */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 4C168BB117E4745100D9404D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C168BC117E4745100D9404D /* InfoPlist.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4C168BD217E4A30600D9404D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C168C0017E4A33200D9404D /* MainStoryboard.storyboard in Resources */, + 4C168BDE17E4A30600D9404D /* InfoPlist.strings in Resources */, + 4C168BE617E4A30600D9404D /* Images.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 4C168B9F17E4745000D9404D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C168BCF17E477F800D9404D /* BCVideoPreviewView.m in Sources */, + 4C168BAE17E4745100D9404D /* BCScannerViewController.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4C168BAF17E4745100D9404D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C168BC317E4745100D9404D /* BCScannerTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4C168BD017E4A30600D9404D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4C168BE417E4A30600D9404D /* AppDelegate.m in Sources */, + 4C168C0317E4A3AE00D9404D /* MainViewController.m in Sources */, + 4C168BE017E4A30600D9404D /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 4C168BBA17E4745100D9404D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4C168BA217E4745000D9404D /* BCScanner */; + targetProxy = 4C168BB917E4745100D9404D /* PBXContainerItemProxy */; + }; + 4C168C0517E4A3FE00D9404D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4C168BA217E4745000D9404D /* BCScanner */; + targetProxy = 4C168C0417E4A3FE00D9404D /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 4C168BBF17E4745100D9404D /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 4C168BC017E4745100D9404D /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + 4C168BDC17E4A30600D9404D /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 4C168BDD17E4A30600D9404D /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 4C168BC417E4745100D9404D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 4C168BC517E4745100D9404D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 4C168BC717E4745100D9404D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DSTROOT = /tmp/BCScanner.dst; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "BCScanner/BCScanner-Prefix.pch"; + OTHER_LDFLAGS = "-ObjC"; + PRIVATE_HEADERS_FOLDER_PATH = "../../Headers/$(PRODUCT_NAME)/Private"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PUBLIC_HEADERS_FOLDER_PATH = "../../Headers/$(PRODUCT_NAME)"; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 4C168BC817E4745100D9404D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DSTROOT = /tmp/BCScanner.dst; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "BCScanner/BCScanner-Prefix.pch"; + OTHER_LDFLAGS = "-ObjC"; + PRIVATE_HEADERS_FOLDER_PATH = "../../Headers/$(PRODUCT_NAME)/Private"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PUBLIC_HEADERS_FOLDER_PATH = "../../Headers/$(PRODUCT_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 4C168BCA17E4745100D9404D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; + BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/BCScannerExample.app/BCScannerExample"; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + "$(DEVELOPER_FRAMEWORKS_DIR)", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "BCScanner/BCScanner-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = "BCScannerTests/BCScannerTests-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUNDLE_LOADER)"; + WRAPPER_EXTENSION = xctest; + }; + name = Debug; + }; + 4C168BCB17E4745100D9404D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; + BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/BCScannerExample.app/BCScannerExample"; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + "$(DEVELOPER_FRAMEWORKS_DIR)", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "BCScanner/BCScanner-Prefix.pch"; + INFOPLIST_FILE = "BCScannerTests/BCScannerTests-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUNDLE_LOADER)"; + WRAPPER_EXTENSION = xctest; + }; + name = Release; + }; + 4C168BFA17E4A30600D9404D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(DEVELOPER_FRAMEWORKS_DIR)", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "BCScannerExample/BCScannerExample-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + ); + INFOPLIST_FILE = "BCScannerExample/BCScannerExample-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + 4C168BFB17E4A30600D9404D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(DEVELOPER_FRAMEWORKS_DIR)", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "BCScannerExample/BCScannerExample-Prefix.pch"; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + ); + INFOPLIST_FILE = "BCScannerExample/BCScannerExample-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 4C168B9E17E4745000D9404D /* Build configuration list for PBXProject "BCScanner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4C168BC417E4745100D9404D /* Debug */, + 4C168BC517E4745100D9404D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4C168BC617E4745100D9404D /* Build configuration list for PBXNativeTarget "BCScanner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4C168BC717E4745100D9404D /* Debug */, + 4C168BC817E4745100D9404D /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; + 4C168BC917E4745100D9404D /* Build configuration list for PBXNativeTarget "BCScannerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4C168BCA17E4745100D9404D /* Debug */, + 4C168BCB17E4745100D9404D /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; + 4C168BF917E4A30600D9404D /* Build configuration list for PBXNativeTarget "BCScannerExample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4C168BFA17E4A30600D9404D /* Debug */, + 4C168BFB17E4A30600D9404D /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4C168B9B17E4745000D9404D /* Project object */; +} diff --git a/BCScanner/BCScanner-Prefix.pch b/BCScanner/BCScanner-Prefix.pch new file mode 100644 index 0000000..37fdbe6 --- /dev/null +++ b/BCScanner/BCScanner-Prefix.pch @@ -0,0 +1,9 @@ +// +// Prefix header +// +// The contents of this file are implicitly included at the beginning of every source file. +// + +#ifdef __OBJC__ + #import +#endif diff --git a/BCScanner/BCScannerViewController.h b/BCScanner/BCScannerViewController.h new file mode 100644 index 0000000..be84644 --- /dev/null +++ b/BCScanner/BCScannerViewController.h @@ -0,0 +1,124 @@ +// +// BCScannerViewController.h +// BCScannerViewController +// +// Copyright 2013 bitecode, Michael Ochs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import + + +extern NSString *const BCScannerQRCode; /// The code type used for QR codes. +extern NSString *const BCScannerUPCECode; + +//extern NSString *const BCScannerCode39Code; +//extern NSString *const BCScannerCode39Mod43Code; + +extern NSString *const BCScannerEAN13Code; +extern NSString *const BCScannerEAN8Code; + +//extern NSString *const BCScannerCode93Code; +//extern NSString *const BCScannerCode128Code; +//extern NSString *const BCScannerPDF417Code; +//extern NSString *const BCScannerAztecCode; + + + + +@protocol BCScannerViewControllerDelegate; + + +/** + * BCScannerViewController is a view controller that wrapps the scanning capabilities + * of iOS7 into a simple to use drop-in view controller for easy integration into your app. + * + * It is build for the purpose of scanning a single or multiple codes in a deticated screen + * and encapsules all the camera handling and metadata gathering. + * + * The view controller can be presented or pushed onto a navigation stack. It is up to you + * to present and dismiss the view controller whenever you need it. + */ +@interface BCScannerViewController : UIViewController + +/** + * This method lets you check for the availability of the native scanner functionality + * provided by AVFoundation. + * + * @note Do not instanciate this class if this method returns NO! + * + * @return YES if native scanning is available, NO otherwise. + */ ++ (BOOL)scannerAvailable; + +/** + * This is the delegate of the scanner. The delegate will get called to notify you about + * codes that were found in the field of view of the camera. + */ +@property (nonatomic, weak, readwrite) id delegate; + +/** + * This is an array of the codes the scanner should look for. The more code types you + * specify, the longer the image analysis will take! + * + * @see BCScannerCode constants + */ +@property (nonatomic, strong, readwrite) NSArray *codeTypes; + +/** + * This is the gesture recognizer that is used to let the user focus and expose to a + * specific point in the field of view. You can access this property when you want to + * more precisely control what taps should be recognized. + */ +@property (nonatomic, weak, readonly) UITapGestureRecognizer *focusAndExposeGestureRecognizer; + +@end + + +@protocol BCScannerViewControllerDelegate + +@optional +/** + * This method is called whenever a new code enters the field of view. + * + * @param scanner The scanner that is calling this delegate + * @param codes A list of all the codes that entered the FOV in this interval + * + * @note If you do a simple scan for the first code you find, you can get the code + * from this method and close the scanner afterwards. + */ +- (void)scanner:(BCScannerViewController *)scanner codesDidEnterFOV:(NSSet *)codes; + +//- (void)scanner:(BCScannerViewController *)scanner codesDidUpdate:(NSSet *)codes; + +/** + * This method is called whenever an existing code leaves the field of view. + * + * @param scanner The scanner that is calling this delegate + * @param codes A list of all the codes that left the FOV in this interval + */ +- (void)scanner:(BCScannerViewController *)scanner codesDidLeaveFOV:(NSSet *)codes; + +/** + * This method lets you specify an image that is shown as an overlay to give the user + * some feedback about how to hold the camera. + * + * This method is called when the scanner configures its interface. + * + * @param scanner The scanner that is calling this delegate + * @return The image you want to be used as HUD + */ +- (UIImage *)scannerHUDImage:(BCScannerViewController *)scanner; + +@end diff --git a/BCScanner/BCScannerViewController.m b/BCScanner/BCScannerViewController.m new file mode 100644 index 0000000..300dc50 --- /dev/null +++ b/BCScanner/BCScannerViewController.m @@ -0,0 +1,369 @@ +// +// BCScannerViewController.m +// BCScannerViewController +// +// Copyright 2013 bitecode, Michael Ochs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "BCScannerViewController.h" + +#import "BCVideoPreviewView.h" + +@import AVFoundation; + + +NSString *const BCScannerQRCode = @"BCScannerQRCode"; +NSString *const BCScannerUPCECode = @"BCScannerUPCECode"; + +//NSString *const BCScannerCode39Code = @"BCScannerCode39Code"; +//NSString *const BCScannerCode39Mod43Code = @"BCScannerCode39Mod43Code"; + +NSString *const BCScannerEAN13Code = @"BCScannerEAN13Code"; +NSString *const BCScannerEAN8Code = @"BCScannerEAN8Code"; + +//NSString *const BCScannerCode93Code = @"BCScannerCode93Code"; +//NSString *const BCScannerCode128Code = @"BCScannerCode128Code"; +//NSString *const BCScannerPDF417Code = @"BCScannerPDF417Code"; +//NSString *const BCScannerAztecCode = @"BCScannerAztecCode"; + + +@interface BCScannerViewController () + +@property (nonatomic, weak, readwrite) UITapGestureRecognizer *focusAndExposeGestureRecognizer; + +@property (nonatomic, strong, readwrite) NSSet *codesInFOV; +@property (nonatomic, weak, readwrite) UIImageView *hudImageView; + +@property (nonatomic, strong, readwrite) AVCaptureSession *session; +@property (nonatomic, weak, readonly) BCVideoPreviewView *previewView; +@property (nonatomic, weak, readwrite) AVCaptureMetadataOutput *metadataOutput; +@property (nonatomic, strong, readwrite) dispatch_queue_t metadataQueue; + +@end + + +static inline CGRect HUDRect(CGRect bounds, UIEdgeInsets padding, CGFloat aspectRatio) +{ + CGRect frame = UIEdgeInsetsInsetRect(bounds, padding); + + CGFloat frameAspectRatio = CGRectGetWidth(frame) / CGRectGetHeight(frame); + CGRect hudRect = frame; + + if (aspectRatio > frameAspectRatio) { + hudRect.size.height = CGRectGetHeight(frame) / aspectRatio; + hudRect.origin.y += (CGRectGetHeight(frame) - CGRectGetHeight(hudRect)) * .5f; + } else { + hudRect.size.width = CGRectGetHeight(frame) * aspectRatio; + hudRect.origin.x += (CGRectGetWidth(frame) - CGRectGetWidth(hudRect)) * .5f; + } + + return CGRectIntegral(hudRect); + +} + + +@implementation BCScannerViewController + +@dynamic previewView; + + ++ (BOOL)scannerAvailable +{ + return ([[[UIDevice currentDevice] systemVersion] compare:@"7.0" options:NSNumericSearch] != NSOrderedAscending); +} + + + +#pragma mark - code parameters + ++ (NSNumber *)aspectRatioForCode:(NSString *)code +{ + static NSDictionary *aspectRatios = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + aspectRatios = @{ BCScannerQRCode: @1, + BCScannerEAN8Code: @1.1833333333, + BCScannerEAN13Code: @1.4198113208, + BCScannerUPCECode: @0.8538812785 }; + }); + return aspectRatios[code]; +} + ++ (NSString *)metadataObjectTypeFromScannerCode:(NSString *)code +{ + static NSDictionary *objectTypes = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + objectTypes = @{ BCScannerQRCode: AVMetadataObjectTypeQRCode, + BCScannerEAN8Code: AVMetadataObjectTypeEAN8Code, + BCScannerEAN13Code: AVMetadataObjectTypeEAN13Code, + BCScannerUPCECode: AVMetadataObjectTypeUPCECode }; + }); + return objectTypes[code]; +} + ++ (NSArray *)metadataObjectTypesFromScannerCodes:(NSArray *)codes +{ + NSMutableArray *objectTypes = [NSMutableArray arrayWithCapacity:codes.count]; + for (NSString *code in codes) { + NSString *objectType = [self metadataObjectTypeFromScannerCode:code]; + if (objectType) { + [objectTypes addObject:objectType]; + } + } + return [objectTypes copy]; +} + + + +#pragma mark - object + +- (id)initWithCoder:(NSCoder *)aDecoder +{ + self = [super initWithCoder:aDecoder]; + if (self) { + _codesInFOV = [NSSet set]; + [self configureCaptureSession]; + } + return self; +} + +- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil +{ + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + if (self) { + _codesInFOV = [NSSet set]; + [self configureCaptureSession]; + } + return self; +} + +- (void)dealloc +{ + [self teardownCaptureSession]; +} + +- (void)configureCaptureSession +{ + AVCaptureSession *session = [[AVCaptureSession alloc] init]; + + NSError *inputError = nil; + AVCaptureDevice *camera = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; + AVCaptureDeviceInput *cameraInput = [[AVCaptureDeviceInput alloc] initWithDevice:camera error:&inputError]; + if (cameraInput) { + if ([session canAddInput:cameraInput]) { + [session addInput:cameraInput]; + } else { + NSLog(@"[BCScanner] could not add capture device!"); + } + } else { + NSLog(@"[BCScanner] could not create capture device: %@", inputError); + } + + AVCaptureMetadataOutput *metadata = [[AVCaptureMetadataOutput alloc] init]; + if ([session canAddOutput:metadata]) { + dispatch_queue_t metadataQueue = dispatch_queue_create("org.bitecode.BCScanner.metadata", NULL); + [metadata setMetadataObjectsDelegate:self queue:metadataQueue]; + [session addOutput:metadata]; + _metadataOutput = metadata; + _metadataQueue = metadataQueue; + } else { + NSLog(@"[BCScanner] could not create metadata output!"); + } + + _session = session; +} + +- (void)teardownCaptureSession +{ + [_session stopRunning]; + _session = nil; + _metadataOutput = nil; + _metadataQueue = NULL; +} + + + +#pragma mark - view handling + +- (void)loadView +{ + self.view = [BCVideoPreviewView new]; +} + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.previewView.session = self.session; + + UIImage *hudImage = [self.delegate scannerHUDImage:self]; + if (hudImage) { + UIImageView *hudImageView = [[UIImageView alloc] initWithImage:hudImage]; + hudImageView.contentMode = UIViewContentModeScaleToFill; + [self.previewView addSubview:hudImageView]; + _hudImageView = hudImageView; + } + + UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(focusAndExpose:)]; + [self.previewView addGestureRecognizer:tapRecognizer]; + self.focusAndExposeGestureRecognizer = tapRecognizer; +} + +- (void)viewWillAppear:(BOOL)animated +{ + [super viewWillAppear:animated]; + + [self.session startRunning]; +} + +- (void)viewDidDisappear:(BOOL)animated +{ + [self.session stopRunning]; + + [super viewDidDisappear:animated]; +} + +- (void)viewDidLayoutSubviews +{ + [super viewDidLayoutSubviews]; + + [self layoutHUD]; +} + +- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration +{ + [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; + + self.previewView.videoOrientation = (AVCaptureVideoOrientation)toInterfaceOrientation; // The enum defs for UIInterfaceOrientation and AVCaptureVideoOrientation are the same! +} + +- (void)layoutHUD +{ + UIEdgeInsets padding = UIEdgeInsetsMake(20.0f, 20.0f, 20.0f, 20.0f); + CGRect bounds = self.previewView.bounds; + bounds.origin.y += self.topLayoutGuide.length; + bounds.size.height -= self.topLayoutGuide.length + self.bottomLayoutGuide.length; + if (CGRectGetHeight(bounds) > CGRectGetWidth(bounds)) { + bounds.origin.y += (CGRectGetHeight(bounds) - CGRectGetWidth(bounds)) * .5f; + bounds.size.height = CGRectGetWidth(bounds); + } else { + bounds.origin.x += (CGRectGetWidth(bounds) - CGRectGetHeight(bounds)) * .5f; + bounds.size.width = CGRectGetHeight(bounds); + } + + self.hudImageView.hidden = (self.codeTypes.count == 0); + + if (self.codeTypes.count > 0) { + NSNumber *aspectRatio = [[self class] aspectRatioForCode:[self.codeTypes lastObject]]; +#if defined(CGFLOAT_IS_DOUBLE) && (CGFLOAT_IS_DOUBLE > 0) + CGFloat rawAspectRatio = [aspectRatio doubleValue]; +#else + CGFloat rawAspectRatio = [aspectRatio floatValue]; +#endif + [UIView performWithoutAnimation:^{ + self.hudImageView.frame = HUDRect(bounds, padding, rawAspectRatio); + }]; + } + + if (self.codeTypes.count > 1) { + NSUInteger count = self.codeTypes.count; + [UIView animateKeyframesWithDuration:1.0*count delay:0.0f options:(UIViewKeyframeAnimationOptionOverrideInheritedOptions | UIViewKeyframeAnimationOptionCalculationModePaced | UIViewKeyframeAnimationOptionRepeat) animations:^{ + [self.codeTypes enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + NSNumber *aspectRatio = [[self class] aspectRatioForCode:obj]; +#if defined(CGFLOAT_IS_DOUBLE) && (CGFLOAT_IS_DOUBLE > 0) + CGFloat rawAspectRatio = [aspectRatio doubleValue]; +#else + CGFloat rawAspectRatio = [aspectRatio floatValue]; +#endif + CGRect frame = HUDRect(bounds, padding, rawAspectRatio); + [UIView addKeyframeWithRelativeStartTime:idx/(double)count relativeDuration:1/(double)count animations:^{ + self.hudImageView.frame = frame; + }]; + }]; + + } completion:NULL]; + } +} + + + +#pragma mark - actions + +- (IBAction)focusAndExpose:(id)sender +{ + if (sender == self.focusAndExposeGestureRecognizer) { + CGPoint location = [self.focusAndExposeGestureRecognizer locationInView:self.previewView]; + [self.previewView focusAtPoint:location]; + [self.previewView exposeAtPoint:location]; + } +} + + + +#pragma mark - capturing + +- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection +{ + NSSet *objectsStillLiving = [NSSet setWithArray:[metadataObjects valueForKeyPath:@"@distinctUnionOfObjects.stringValue"]]; + + NSMutableSet *objectsAdded = [NSMutableSet setWithSet:objectsStillLiving]; + [objectsAdded minusSet:self.codesInFOV]; + +// NSMutableSet *objectsUpdated = [NSMutableSet setWithSet:objectsStillLiving]; +// [objectsUpdated intersectSet:self.codesInFOV]; + + NSMutableSet *objectsMissing = [NSMutableSet setWithSet:self.codesInFOV]; + [objectsMissing minusSet:objectsStillLiving]; + + self.codesInFOV = objectsStillLiving; + + dispatch_sync(dispatch_get_main_queue(), ^{ + if (objectsAdded.count > 0 && [self.delegate respondsToSelector:@selector(scanner:codesDidEnterFOV:)]) { + [self.delegate scanner:self codesDidEnterFOV:[objectsAdded copy]]; + } +// if (objectsUpdated.count > 0 && [self.delegate respondsToSelector:@selector(scanner:codesDidUpdate:)]) { +// [self.delegate scanner:self codesDidUpdate:[objectsUpdated copy]]; +// } + if (objectsMissing.count > 0 && [self.delegate respondsToSelector:@selector(scanner:codesDidLeaveFOV:)]) { + [self.delegate scanner:self codesDidLeaveFOV:[objectsMissing copy]]; + } + }); +} + + + +#pragma mark - accessors + +- (BCVideoPreviewView *)previewView +{ + if (self.isViewLoaded) { + return (BCVideoPreviewView *)self.view; + } else { + return nil; + } +} + +- (void)setCodeTypes:(NSArray *)codes +{ + _codeTypes = codes; + NSArray *metadataObjectTypes = [[self class] metadataObjectTypesFromScannerCodes:codes]; + [self.metadataOutput setMetadataObjectTypes:metadataObjectTypes]; + if (self.isViewLoaded) { + [self layoutHUD]; + } +} + +@end diff --git a/BCScanner/Private/BCVideoPreviewView.h b/BCScanner/Private/BCVideoPreviewView.h new file mode 100644 index 0000000..c6bd0b9 --- /dev/null +++ b/BCScanner/Private/BCVideoPreviewView.h @@ -0,0 +1,34 @@ +// +// BCVideoPreviewView.h +// BCScanner +// +// Copyright 2013 bitecode, Michael Ochs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import + + +@import AVFoundation; + + +@interface BCVideoPreviewView : UIView + +@property (nonatomic, strong, readwrite) AVCaptureSession *session; +@property (nonatomic, assign, readwrite) AVCaptureVideoOrientation videoOrientation; + +- (BOOL)focusAtPoint:(CGPoint)point; +- (BOOL)exposeAtPoint:(CGPoint)point; + +@end diff --git a/BCScanner/Private/BCVideoPreviewView.m b/BCScanner/Private/BCVideoPreviewView.m new file mode 100644 index 0000000..61c2eb0 --- /dev/null +++ b/BCScanner/Private/BCVideoPreviewView.m @@ -0,0 +1,162 @@ +// +// BCVideoPreviewView.m +// BCScanner +// +// Copyright 2013 bitecode, Michael Ochs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "BCVideoPreviewView.h" + + +@interface BCVideoPreviewView () + +@property (nonatomic, strong, readonly) AVCaptureVideoPreviewLayer *previewLayer; + +@end + + +@implementation BCVideoPreviewView + +@dynamic session; +@dynamic previewLayer; +@dynamic videoOrientation; + ++ (Class)layerClass +{ + return [AVCaptureVideoPreviewLayer class]; +} + +- (id)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + [self configureLayer]; + } + return self; +} + +- (void)awakeFromNib +{ + [super awakeFromNib]; + + [self configureLayer]; +} + +- (void)configureLayer +{ + self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; +} + +- (AVCaptureVideoPreviewLayer *)previewLayer +{ + return (AVCaptureVideoPreviewLayer *)self.layer; +} + + + +#pragma mark - camera handling + +- (AVCaptureDevice *)captureDevice +{ + NSArray *inputPorts = [self.previewLayer.connection inputPorts]; + for (AVCaptureInputPort *port in inputPorts) { + if ([[port mediaType] isEqualToString:AVMediaTypeVideo]) { + AVCaptureInput *input = [port input]; + if ([input isKindOfClass:[AVCaptureDeviceInput class]]) { + AVCaptureDevice *device = [(AVCaptureDeviceInput *)input device]; + return device; + } + } + } + return nil; +} + +- (BOOL)focusAtPoint:(CGPoint)point +{ + CGPoint convertedPoint = [self.previewLayer captureDevicePointOfInterestForPoint:point]; + + AVCaptureDevice* videoDevice = [self captureDevice]; + if ([videoDevice isFocusPointOfInterestSupported] && [videoDevice isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]) { + NSError* configurationError = nil; + if ([videoDevice lockForConfiguration:&configurationError]) { + [videoDevice setFocusMode:AVCaptureFocusModeContinuousAutoFocus]; + [videoDevice setFocusPointOfInterest:convertedPoint]; + [videoDevice unlockForConfiguration]; + return YES; + + } else { + NSLog(@"[BCScanner] Can not configure focus for input device: %@", configurationError); + return NO; + } + + } else { + return NO; + } +} + +- (BOOL)exposeAtPoint:(CGPoint)point +{ + CGPoint convertedPoint = [self.previewLayer captureDevicePointOfInterestForPoint:point]; + + AVCaptureDevice* videoDevice = [self captureDevice]; + if ([videoDevice isExposurePointOfInterestSupported] && [videoDevice isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure]) { + NSError* configurationError = nil; + if ([videoDevice lockForConfiguration:&configurationError]) { + [videoDevice setExposureMode:AVCaptureExposureModeContinuousAutoExposure]; + [videoDevice setExposurePointOfInterest:convertedPoint]; + [videoDevice unlockForConfiguration]; + return YES; + + } else { + NSLog(@"[BCScanner] Can not configure exposure for input device: %@", configurationError); + return NO; + } + + } else { + return NO; + } +} + + + +#pragma mark - accessors + +- (void)setSession:(AVCaptureSession *)session +{ + [self.previewLayer setSession:session]; +} + +- (AVCaptureSession *)session +{ + return [self.previewLayer session]; +} + +- (void)setVideoOrientation:(AVCaptureVideoOrientation)videoOrientation +{ + if ([self.previewLayer.connection isVideoOrientationSupported]) { + self.previewLayer.connection.videoOrientation = videoOrientation; + } +} + +- (AVCaptureVideoOrientation)videoOrientation +{ + if ([self.previewLayer.connection isVideoOrientationSupported]) { + return self.previewLayer.connection.videoOrientation; + } else { + return 0; + } +} + +@end diff --git a/BCScannerExample/AppDelegate.h b/BCScannerExample/AppDelegate.h new file mode 100644 index 0000000..b414f58 --- /dev/null +++ b/BCScannerExample/AppDelegate.h @@ -0,0 +1,26 @@ +// +// AppDelegate.h +// BCScannerExample +// +// Copyright 2013 bitecode, Michael Ochs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + +@end diff --git a/BCScannerExample/AppDelegate.m b/BCScannerExample/AppDelegate.m new file mode 100644 index 0000000..9ab4bfd --- /dev/null +++ b/BCScannerExample/AppDelegate.m @@ -0,0 +1,56 @@ +// +// AppDelegate.m +// BCScannerExample +// +// Copyright 2013 bitecode, Michael Ochs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "AppDelegate.h" + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application +{ + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application +{ + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application +{ + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application +{ + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application +{ + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/BCScannerExample/BCScannerExample-Info.plist b/BCScannerExample/BCScannerExample-Info.plist new file mode 100644 index 0000000..cb9dd16 --- /dev/null +++ b/BCScannerExample/BCScannerExample-Info.plist @@ -0,0 +1,40 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + org.bitecode.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + UIMainStoryboardFile + MainStoryboard + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/BCScannerExample/BCScannerExample-Prefix.pch b/BCScannerExample/BCScannerExample-Prefix.pch new file mode 100644 index 0000000..ccc4f43 --- /dev/null +++ b/BCScannerExample/BCScannerExample-Prefix.pch @@ -0,0 +1,16 @@ +// +// Prefix header +// +// The contents of this file are implicitly included at the beginning of every source file. +// + +#import + +#ifndef __IPHONE_3_0 +#warning "This project uses features only available in iOS SDK 3.0 and later." +#endif + +#ifdef __OBJC__ + #import + #import +#endif diff --git a/BCScannerExample/HUD.png b/BCScannerExample/HUD.png new file mode 100644 index 0000000..ed2bc4f Binary files /dev/null and b/BCScannerExample/HUD.png differ diff --git a/BCScannerExample/HUD@2x.png b/BCScannerExample/HUD@2x.png new file mode 100644 index 0000000..fd92c1b Binary files /dev/null and b/BCScannerExample/HUD@2x.png differ diff --git a/BCScannerExample/Images.xcassets/AppIcon.appiconset/Contents.json b/BCScannerExample/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..a396706 --- /dev/null +++ b/BCScannerExample/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/BCScannerExample/Images.xcassets/HUD.imageset/Contents.json b/BCScannerExample/Images.xcassets/HUD.imageset/Contents.json new file mode 100644 index 0000000..46dded6 --- /dev/null +++ b/BCScannerExample/Images.xcassets/HUD.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "resizing" : { + "mode" : "9-part", + "center" : { + "mode" : "fill", + "width" : 1, + "height" : 1 + }, + "capInsets" : { + "bottom" : 20, + "top" : 20, + "right" : 20, + "left" : 21 + } + }, + "idiom" : "universal", + "filename" : "HUD.png", + "scale" : "1x" + }, + { + "resizing" : { + "mode" : "9-part", + "center" : { + "mode" : "fill", + "width" : 1, + "height" : 1 + }, + "capInsets" : { + "bottom" : 41, + "top" : 42, + "right" : 41, + "left" : 42 + } + }, + "idiom" : "universal", + "filename" : "HUD@2x.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/BCScannerExample/Images.xcassets/HUD.imageset/HUD.png b/BCScannerExample/Images.xcassets/HUD.imageset/HUD.png new file mode 100644 index 0000000..ed2bc4f Binary files /dev/null and b/BCScannerExample/Images.xcassets/HUD.imageset/HUD.png differ diff --git a/BCScannerExample/Images.xcassets/HUD.imageset/HUD@2x.png b/BCScannerExample/Images.xcassets/HUD.imageset/HUD@2x.png new file mode 100644 index 0000000..fd92c1b Binary files /dev/null and b/BCScannerExample/Images.xcassets/HUD.imageset/HUD@2x.png differ diff --git a/BCScannerExample/Images.xcassets/LaunchImage.launchimage/Contents.json b/BCScannerExample/Images.xcassets/LaunchImage.launchimage/Contents.json new file mode 100644 index 0000000..c79ebd3 --- /dev/null +++ b/BCScannerExample/Images.xcassets/LaunchImage.launchimage/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "orientation" : "portrait", + "idiom" : "iphone", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "subtype" : "retina4", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/BCScannerExample/MainStoryboard.storyboard b/BCScannerExample/MainStoryboard.storyboard new file mode 100644 index 0000000..0e1817b --- /dev/null +++ b/BCScannerExample/MainStoryboard.storyboard @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/BCScannerExample/MainViewController.h b/BCScannerExample/MainViewController.h new file mode 100644 index 0000000..b0b333c --- /dev/null +++ b/BCScannerExample/MainViewController.h @@ -0,0 +1,26 @@ +// +// MainViewController.h +// BCScanner +// +// Copyright 2013 bitecode, Michael Ochs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import + +@interface MainViewController : UIViewController + +- (IBAction)openScanner:(id)sender; + +@end diff --git a/BCScannerExample/MainViewController.m b/BCScannerExample/MainViewController.m new file mode 100644 index 0000000..090d2d3 --- /dev/null +++ b/BCScannerExample/MainViewController.m @@ -0,0 +1,66 @@ +// +// MainViewController.m +// BCScanner +// +// Copyright 2013 bitecode, Michael Ochs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "MainViewController.h" + +#import "../BCScanner/BCScannerViewController.h" + + +@interface MainViewController () + +@end + + +@implementation MainViewController + +- (IBAction)openScanner:(id)sender +{ + if ([BCScannerViewController scannerAvailable]) { + BCScannerViewController *scanner = [[BCScannerViewController alloc] init]; + scanner.delegate = self; + scanner.codeTypes = @[ BCScannerQRCode, BCScannerEAN8Code, BCScannerEAN13Code, BCScannerUPCECode ]; + [self.navigationController pushViewController:scanner animated:YES]; + } +} + + + +#pragma mark - BCScannerViewControllerDelegate + +- (void)scanner:(BCScannerViewController *)scanner codesDidEnterFOV:(NSSet *)codes +{ + NSLog(@"Added: [%@]", codes); +} + +//- (void)scanner:(BCScannerViewController *)scanner codesDidUpdate:(NSSet *)codes +//{ +// NSLog(@"Updated: [%lu]", (unsigned long)codes.count); +//} + +- (void)scanner:(BCScannerViewController *)scanner codesDidLeaveFOV:(NSSet *)codes +{ + NSLog(@"Deleted: [%@]", codes); +} + +- (UIImage *)scannerHUDImage:(BCScannerViewController *)scanner +{ + return [UIImage imageNamed:@"HUD"]; +} + +@end diff --git a/BCScannerExample/en.lproj/InfoPlist.strings b/BCScannerExample/en.lproj/InfoPlist.strings new file mode 100644 index 0000000..477b28f --- /dev/null +++ b/BCScannerExample/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/BCScannerExample/main.m b/BCScannerExample/main.m new file mode 100644 index 0000000..ab340f7 --- /dev/null +++ b/BCScannerExample/main.m @@ -0,0 +1,29 @@ +// +// main.m +// BCScannerExample +// +// Copyright 2013 bitecode, Michael Ochs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import + +#import "AppDelegate.h" + +int main(int argc, char * argv[]) +{ + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/BCScannerTests/BCScannerTests-Info.plist b/BCScannerTests/BCScannerTests-Info.plist new file mode 100644 index 0000000..1356420 --- /dev/null +++ b/BCScannerTests/BCScannerTests-Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + org.bitecode.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/BCScannerTests/BCScannerTests.m b/BCScannerTests/BCScannerTests.m new file mode 100644 index 0000000..86c70cc --- /dev/null +++ b/BCScannerTests/BCScannerTests.m @@ -0,0 +1,45 @@ +// +// BCScannerTests.m +// BCScannerTests +// +// Copyright 2013 bitecode, Michael Ochs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import + +@interface BCScannerTests : XCTestCase + +@end + +@implementation BCScannerTests + +- (void)setUp +{ + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown +{ + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testExample +{ + XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); +} + +@end diff --git a/BCScannerTests/en.lproj/InfoPlist.strings b/BCScannerTests/en.lproj/InfoPlist.strings new file mode 100644 index 0000000..477b28f --- /dev/null +++ b/BCScannerTests/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/README.md b/README.md index 4710776..0fedf0b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,47 @@ -BCScanner -========= +# BCScanner -A barcode and qr code scanner that wraps the iOS7 scanning capabilities in a UIViewController +BCScanner is a barcode and qr code scanner library that makes use of the new iOS7 features build into AVFoundation. It lets you easily integrate a barcode or qr code scanner into your application without dealing with AVFoundation. + +## Requirements + +BCScanner is bild for the use with iOS7. If you still do support iOS6, make sure to check the +[BCScanner scannerAvailable] method bevore making any other calls to BCScanner. BCScanner is not compatible with iOS6 because of the internal use of new AVFoundation API. +BCScanner also requires you to use ARC. + +## Dependencies + +- UIKit +- AVFoundation +- QuartzCore + +## Beta + +BCScanner is beta. Some issues will get fixed within the next couple of weeks. Feel free to send pull requests. The open TODOs are: +- When using multiple codes together with a hud immage the animation will break when relayouting the screen (e.g. when rotating). +- There should be a block based API for those use cases where only scanning one barcode is required. +- As this is beta, there might be changes in the API that may break the current API. +- Not all supported code types of AVFoundation are added to BCScanner yet. Currently supported types are: QR, UPCE, EAN8 and EAN13. +- There are no unit tests at the moment. + +## Install + +Add the BCScanner project to your project. +Set the header search path to "$(BUILT_PRODUCTS_DIR)/../../Headers". (Including the quotes!) +Add BCScanner as a target dependency and in the linker phase. +Make sure to set the -ObjC linker flag in your build settings. +See BCScannerExample target for a reference, if you have problems, linking the library. + +## Licence + +Copyright 2013 bitecode, Michael Ochs + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file