├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── STQRCodeController.podspec ├── STQRCodeController.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ └── STQRCodeController.xcscheme ├── STQRCodeController.xcworkspace └── contents.xcworkspacedata ├── STQRCodeController ├── Info.plist ├── NSBundle+STQRCodeController.h ├── NSBundle+STQRCodeController.m ├── STQRCodeAlert.h ├── STQRCodeAlert.m ├── STQRCodeConst.h ├── STQRCodeConst.m ├── STQRCodeController.bundle │ ├── st_lightNormal@2x.png │ ├── st_lightSelect@2x.png │ ├── st_noticeMusic.wav │ ├── st_scanBackground@2x.png │ └── st_scanLine@2x.png ├── STQRCodeController.h ├── STQRCodeController.m ├── STQRCodeReaderView.h └── STQRCodeReaderView.m └── STQRCodeControllerDemo ├── STQRCodeControllerDemo.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata └── STQRCodeControllerDemo ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets └── AppIcon.appiconset │ └── Contents.json ├── Base.lproj └── LaunchScreen.storyboard ├── Info.plist ├── TestController.h ├── TestController.m └── main.m /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xcuserstate 23 | 24 | ## Obj-C/Swift specific 25 | *.hmap 26 | *.ipa 27 | *.dSYM.zip 28 | *.dSYM 29 | 30 | # CocoaPods 31 | # 32 | # We recommend against adding the Pods directory to your .gitignore. However 33 | # you should judge for yourself, the pros and cons are mentioned at: 34 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 35 | # 36 | # Pods/ 37 | 38 | # Carthage 39 | # 40 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 41 | # Carthage/Checkouts 42 | 43 | Carthage/Build 44 | 45 | # fastlane 46 | # 47 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 48 | # screenshots whenever they are needed. 49 | # For more information about the recommended setup visit: 50 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 51 | 52 | fastlane/report.xml 53 | fastlane/screenshots 54 | 55 | #Code Injection 56 | # 57 | # After new code Injection tools there's a generated folder /iOSInjectionProject 58 | # https://github.com/johnno1962/injectionforxcode 59 | 60 | iOSInjectionProject/ 61 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 版本信息 2 | 3 | ## 1.4 4 | 1. 添加环境检查,如果在昏暗的环境下,首次进入自动开启,之后就关闭自动 5 | 2. 在iOS10.3.1测试通过 6 | 7 | ## 1.3 8 | 1. 添加后台监听 9 | 10 | ## 1.2 11 | 1. 添加提示语 12 | 2. 修改状态栏在跳转相册时候的问题 13 | 3. 完善Carthage使用 14 | 4. 对iOS7支持 15 | 16 | ## 1.1 17 | 1. 添加权限检测 18 | 2. 添加Carthage的支持 19 | 20 | ## 1.0 21 | 1. 支持iOS8以上,分别在iOS8.2、iOS9.3、iOS10.1的系统中测试通过 22 | 2. 支持图片识别,可从相册中获取 23 | 3. 支持闪关灯,如果设备不支持闪关灯,闪光灯按钮将不显示 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 沈天 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # STQRCodeController 2 | 3 | ![License MIT](https://img.shields.io/github/license/mashape/apistatus.svg?maxAge=2592000) 4 | ![Pod version](https://img.shields.io/cocoapods/v/STQRCodeController.svg?style=flat) 5 | [![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 6 | [![Platform info](https://img.shields.io/cocoapods/p/STQRCodeController.svg?style=flat)](http://cocoadocs.org/docsets/STQRCodeController) 7 | 8 | 一个简单使用的二维码识别控制器,代码量不到1000行 9 | 10 | ## 使用方法 11 | 12 | 使用举例: 13 | 14 | STQRCodeController *codeVC = [[STQRCodeController alloc]init]; 15 | codeVC.delegate = self; 16 | UINavigationController *navVC = [[UINavigationController alloc]initWithRootViewController:codeVC]; 17 | [self presentViewController:navVC animated:YES completion:nil]; 18 | 19 | 20 | 添加对iOS10的支持 21 | 在info.plist中添加 22 | 23 | NSCameraUsageDescription 24 | 开启相机 25 | NSPhotoLibraryUsageDescription 26 | 开启相册 27 | 28 | ## 效果图 29 | ![](https://raw.githubusercontent.com/STShenZhaoliang/STImage/master/STQRCodeController/STQRCodeController.gif) 30 | 31 | ## [版本信息](https://github.com/STShenZhaoliang/STQRCodeController/blob/master/CHANGELOG.md) 32 | -------------------------------------------------------------------------------- /STQRCodeController.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'STQRCodeController' 3 | s.version = '1.4' 4 | s.license = { :type => 'MIT', :file => 'LICENSE'} 5 | s.summary = '千行代码搞定二维码扫描' 6 | s.homepage = 'https://github.com/STShenZhaoliang' 7 | s.author = { 'STShenZhaoliang' => '409178030@qq.com' } 8 | s.source = { 9 | :git => 'https://github.com/STShenZhaoliang/STQRCodeController.git', 10 | :tag => s.version.to_s 11 | } 12 | s.ios.deployment_target = '7.0' 13 | s.source_files = "STQRCodeController/*.{h,m}" 14 | s.resource = "STQRCodeController/STQRCodeController.bundle" 15 | s.requires_arc = true 16 | end 17 | -------------------------------------------------------------------------------- /STQRCodeController.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 709EB16A1E25DC7B00342CB1 /* STQRCodeController.h in Headers */ = {isa = PBXBuildFile; fileRef = 709EB1681E25DC7B00342CB1 /* STQRCodeController.h */; settings = {ATTRIBUTES = (Public, ); }; }; 11 | 709EB17A1E25DD1D00342CB1 /* STQRCodeReaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 709EB1701E25DD1D00342CB1 /* STQRCodeReaderView.m */; }; 12 | 709EB17B1E25DD1D00342CB1 /* STQRCodeController.m in Sources */ = {isa = PBXBuildFile; fileRef = 709EB1711E25DD1D00342CB1 /* STQRCodeController.m */; }; 13 | 709EB17C1E25DD1D00342CB1 /* STQRCodeController.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 709EB1721E25DD1D00342CB1 /* STQRCodeController.bundle */; }; 14 | 709EB17D1E25DD1D00342CB1 /* NSBundle+STQRCodeController.h in Headers */ = {isa = PBXBuildFile; fileRef = 709EB1731E25DD1D00342CB1 /* NSBundle+STQRCodeController.h */; }; 15 | 709EB17E1E25DD1D00342CB1 /* NSBundle+STQRCodeController.m in Sources */ = {isa = PBXBuildFile; fileRef = 709EB1741E25DD1D00342CB1 /* NSBundle+STQRCodeController.m */; }; 16 | 709EB17F1E25DD1D00342CB1 /* STQRCodeReaderView.h in Headers */ = {isa = PBXBuildFile; fileRef = 709EB1751E25DD1D00342CB1 /* STQRCodeReaderView.h */; }; 17 | 709EB1801E25DD1D00342CB1 /* STQRCodeConst.h in Headers */ = {isa = PBXBuildFile; fileRef = 709EB1761E25DD1D00342CB1 /* STQRCodeConst.h */; }; 18 | 709EB1811E25DD1D00342CB1 /* STQRCodeConst.m in Sources */ = {isa = PBXBuildFile; fileRef = 709EB1771E25DD1D00342CB1 /* STQRCodeConst.m */; }; 19 | 709EB1821E25DD1D00342CB1 /* STQRCodeAlert.h in Headers */ = {isa = PBXBuildFile; fileRef = 709EB1781E25DD1D00342CB1 /* STQRCodeAlert.h */; }; 20 | 709EB1831E25DD1D00342CB1 /* STQRCodeAlert.m in Sources */ = {isa = PBXBuildFile; fileRef = 709EB1791E25DD1D00342CB1 /* STQRCodeAlert.m */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXFileReference section */ 24 | 709EB1651E25DC7B00342CB1 /* STQRCodeController.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = STQRCodeController.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 25 | 709EB1681E25DC7B00342CB1 /* STQRCodeController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = STQRCodeController.h; sourceTree = ""; }; 26 | 709EB1691E25DC7B00342CB1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 27 | 709EB1701E25DD1D00342CB1 /* STQRCodeReaderView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STQRCodeReaderView.m; sourceTree = ""; }; 28 | 709EB1711E25DD1D00342CB1 /* STQRCodeController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STQRCodeController.m; sourceTree = ""; }; 29 | 709EB1721E25DD1D00342CB1 /* STQRCodeController.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = STQRCodeController.bundle; sourceTree = ""; }; 30 | 709EB1731E25DD1D00342CB1 /* NSBundle+STQRCodeController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSBundle+STQRCodeController.h"; sourceTree = ""; }; 31 | 709EB1741E25DD1D00342CB1 /* NSBundle+STQRCodeController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSBundle+STQRCodeController.m"; sourceTree = ""; }; 32 | 709EB1751E25DD1D00342CB1 /* STQRCodeReaderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STQRCodeReaderView.h; sourceTree = ""; }; 33 | 709EB1761E25DD1D00342CB1 /* STQRCodeConst.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STQRCodeConst.h; sourceTree = ""; }; 34 | 709EB1771E25DD1D00342CB1 /* STQRCodeConst.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STQRCodeConst.m; sourceTree = ""; }; 35 | 709EB1781E25DD1D00342CB1 /* STQRCodeAlert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STQRCodeAlert.h; sourceTree = ""; }; 36 | 709EB1791E25DD1D00342CB1 /* STQRCodeAlert.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STQRCodeAlert.m; sourceTree = ""; }; 37 | /* End PBXFileReference section */ 38 | 39 | /* Begin PBXFrameworksBuildPhase section */ 40 | 709EB1611E25DC7B00342CB1 /* Frameworks */ = { 41 | isa = PBXFrameworksBuildPhase; 42 | buildActionMask = 2147483647; 43 | files = ( 44 | ); 45 | runOnlyForDeploymentPostprocessing = 0; 46 | }; 47 | /* End PBXFrameworksBuildPhase section */ 48 | 49 | /* Begin PBXGroup section */ 50 | 709EB15B1E25DC7B00342CB1 = { 51 | isa = PBXGroup; 52 | children = ( 53 | 709EB1671E25DC7B00342CB1 /* STQRCodeController */, 54 | 709EB1661E25DC7B00342CB1 /* Products */, 55 | ); 56 | sourceTree = ""; 57 | }; 58 | 709EB1661E25DC7B00342CB1 /* Products */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | 709EB1651E25DC7B00342CB1 /* STQRCodeController.framework */, 62 | ); 63 | name = Products; 64 | sourceTree = ""; 65 | }; 66 | 709EB1671E25DC7B00342CB1 /* STQRCodeController */ = { 67 | isa = PBXGroup; 68 | children = ( 69 | 709EB1751E25DD1D00342CB1 /* STQRCodeReaderView.h */, 70 | 709EB1701E25DD1D00342CB1 /* STQRCodeReaderView.m */, 71 | 709EB1681E25DC7B00342CB1 /* STQRCodeController.h */, 72 | 709EB1711E25DD1D00342CB1 /* STQRCodeController.m */, 73 | 709EB1721E25DD1D00342CB1 /* STQRCodeController.bundle */, 74 | 709EB1731E25DD1D00342CB1 /* NSBundle+STQRCodeController.h */, 75 | 709EB1741E25DD1D00342CB1 /* NSBundle+STQRCodeController.m */, 76 | 709EB1761E25DD1D00342CB1 /* STQRCodeConst.h */, 77 | 709EB1771E25DD1D00342CB1 /* STQRCodeConst.m */, 78 | 709EB1781E25DD1D00342CB1 /* STQRCodeAlert.h */, 79 | 709EB1791E25DD1D00342CB1 /* STQRCodeAlert.m */, 80 | 709EB1691E25DC7B00342CB1 /* Info.plist */, 81 | ); 82 | path = STQRCodeController; 83 | sourceTree = ""; 84 | }; 85 | /* End PBXGroup section */ 86 | 87 | /* Begin PBXHeadersBuildPhase section */ 88 | 709EB1621E25DC7B00342CB1 /* Headers */ = { 89 | isa = PBXHeadersBuildPhase; 90 | buildActionMask = 2147483647; 91 | files = ( 92 | 709EB1821E25DD1D00342CB1 /* STQRCodeAlert.h in Headers */, 93 | 709EB17D1E25DD1D00342CB1 /* NSBundle+STQRCodeController.h in Headers */, 94 | 709EB1801E25DD1D00342CB1 /* STQRCodeConst.h in Headers */, 95 | 709EB17F1E25DD1D00342CB1 /* STQRCodeReaderView.h in Headers */, 96 | 709EB16A1E25DC7B00342CB1 /* STQRCodeController.h in Headers */, 97 | ); 98 | runOnlyForDeploymentPostprocessing = 0; 99 | }; 100 | /* End PBXHeadersBuildPhase section */ 101 | 102 | /* Begin PBXNativeTarget section */ 103 | 709EB1641E25DC7B00342CB1 /* STQRCodeController */ = { 104 | isa = PBXNativeTarget; 105 | buildConfigurationList = 709EB16D1E25DC7B00342CB1 /* Build configuration list for PBXNativeTarget "STQRCodeController" */; 106 | buildPhases = ( 107 | 709EB1601E25DC7B00342CB1 /* Sources */, 108 | 709EB1611E25DC7B00342CB1 /* Frameworks */, 109 | 709EB1621E25DC7B00342CB1 /* Headers */, 110 | 709EB1631E25DC7B00342CB1 /* Resources */, 111 | ); 112 | buildRules = ( 113 | ); 114 | dependencies = ( 115 | ); 116 | name = STQRCodeController; 117 | productName = STQRCodeController; 118 | productReference = 709EB1651E25DC7B00342CB1 /* STQRCodeController.framework */; 119 | productType = "com.apple.product-type.framework"; 120 | }; 121 | /* End PBXNativeTarget section */ 122 | 123 | /* Begin PBXProject section */ 124 | 709EB15C1E25DC7B00342CB1 /* Project object */ = { 125 | isa = PBXProject; 126 | attributes = { 127 | LastUpgradeCheck = 0810; 128 | ORGANIZATIONNAME = ST; 129 | TargetAttributes = { 130 | 709EB1641E25DC7B00342CB1 = { 131 | CreatedOnToolsVersion = 8.1; 132 | DevelopmentTeam = Z25J3BA353; 133 | ProvisioningStyle = Automatic; 134 | }; 135 | }; 136 | }; 137 | buildConfigurationList = 709EB15F1E25DC7B00342CB1 /* Build configuration list for PBXProject "STQRCodeController" */; 138 | compatibilityVersion = "Xcode 3.2"; 139 | developmentRegion = English; 140 | hasScannedForEncodings = 0; 141 | knownRegions = ( 142 | en, 143 | ); 144 | mainGroup = 709EB15B1E25DC7B00342CB1; 145 | productRefGroup = 709EB1661E25DC7B00342CB1 /* Products */; 146 | projectDirPath = ""; 147 | projectRoot = ""; 148 | targets = ( 149 | 709EB1641E25DC7B00342CB1 /* STQRCodeController */, 150 | ); 151 | }; 152 | /* End PBXProject section */ 153 | 154 | /* Begin PBXResourcesBuildPhase section */ 155 | 709EB1631E25DC7B00342CB1 /* Resources */ = { 156 | isa = PBXResourcesBuildPhase; 157 | buildActionMask = 2147483647; 158 | files = ( 159 | 709EB17C1E25DD1D00342CB1 /* STQRCodeController.bundle in Resources */, 160 | ); 161 | runOnlyForDeploymentPostprocessing = 0; 162 | }; 163 | /* End PBXResourcesBuildPhase section */ 164 | 165 | /* Begin PBXSourcesBuildPhase section */ 166 | 709EB1601E25DC7B00342CB1 /* Sources */ = { 167 | isa = PBXSourcesBuildPhase; 168 | buildActionMask = 2147483647; 169 | files = ( 170 | 709EB1831E25DD1D00342CB1 /* STQRCodeAlert.m in Sources */, 171 | 709EB17B1E25DD1D00342CB1 /* STQRCodeController.m in Sources */, 172 | 709EB17A1E25DD1D00342CB1 /* STQRCodeReaderView.m in Sources */, 173 | 709EB1811E25DD1D00342CB1 /* STQRCodeConst.m in Sources */, 174 | 709EB17E1E25DD1D00342CB1 /* NSBundle+STQRCodeController.m in Sources */, 175 | ); 176 | runOnlyForDeploymentPostprocessing = 0; 177 | }; 178 | /* End PBXSourcesBuildPhase section */ 179 | 180 | /* Begin XCBuildConfiguration section */ 181 | 709EB16B1E25DC7B00342CB1 /* Debug */ = { 182 | isa = XCBuildConfiguration; 183 | buildSettings = { 184 | ALWAYS_SEARCH_USER_PATHS = NO; 185 | CLANG_ANALYZER_NONNULL = YES; 186 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 187 | CLANG_CXX_LIBRARY = "libc++"; 188 | CLANG_ENABLE_MODULES = YES; 189 | CLANG_ENABLE_OBJC_ARC = YES; 190 | CLANG_WARN_BOOL_CONVERSION = YES; 191 | CLANG_WARN_CONSTANT_CONVERSION = YES; 192 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 193 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 194 | CLANG_WARN_EMPTY_BODY = YES; 195 | CLANG_WARN_ENUM_CONVERSION = YES; 196 | CLANG_WARN_INFINITE_RECURSION = YES; 197 | CLANG_WARN_INT_CONVERSION = YES; 198 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 199 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 200 | CLANG_WARN_UNREACHABLE_CODE = YES; 201 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 202 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 203 | COPY_PHASE_STRIP = NO; 204 | CURRENT_PROJECT_VERSION = 1; 205 | DEBUG_INFORMATION_FORMAT = dwarf; 206 | ENABLE_STRICT_OBJC_MSGSEND = YES; 207 | ENABLE_TESTABILITY = YES; 208 | GCC_C_LANGUAGE_STANDARD = gnu99; 209 | GCC_DYNAMIC_NO_PIC = NO; 210 | GCC_NO_COMMON_BLOCKS = YES; 211 | GCC_OPTIMIZATION_LEVEL = 0; 212 | GCC_PREPROCESSOR_DEFINITIONS = ( 213 | "DEBUG=1", 214 | "$(inherited)", 215 | ); 216 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 217 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 218 | GCC_WARN_UNDECLARED_SELECTOR = YES; 219 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 220 | GCC_WARN_UNUSED_FUNCTION = YES; 221 | GCC_WARN_UNUSED_VARIABLE = YES; 222 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 223 | MTL_ENABLE_DEBUG_INFO = YES; 224 | ONLY_ACTIVE_ARCH = NO; 225 | SDKROOT = iphoneos; 226 | TARGETED_DEVICE_FAMILY = "1,2"; 227 | VERSIONING_SYSTEM = "apple-generic"; 228 | VERSION_INFO_PREFIX = ""; 229 | }; 230 | name = Debug; 231 | }; 232 | 709EB16C1E25DC7B00342CB1 /* Release */ = { 233 | isa = XCBuildConfiguration; 234 | buildSettings = { 235 | ALWAYS_SEARCH_USER_PATHS = NO; 236 | CLANG_ANALYZER_NONNULL = YES; 237 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 238 | CLANG_CXX_LIBRARY = "libc++"; 239 | CLANG_ENABLE_MODULES = YES; 240 | CLANG_ENABLE_OBJC_ARC = YES; 241 | CLANG_WARN_BOOL_CONVERSION = YES; 242 | CLANG_WARN_CONSTANT_CONVERSION = YES; 243 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 244 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 245 | CLANG_WARN_EMPTY_BODY = YES; 246 | CLANG_WARN_ENUM_CONVERSION = YES; 247 | CLANG_WARN_INFINITE_RECURSION = YES; 248 | CLANG_WARN_INT_CONVERSION = YES; 249 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 250 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 251 | CLANG_WARN_UNREACHABLE_CODE = YES; 252 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 253 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 254 | COPY_PHASE_STRIP = NO; 255 | CURRENT_PROJECT_VERSION = 1; 256 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 257 | ENABLE_NS_ASSERTIONS = NO; 258 | ENABLE_STRICT_OBJC_MSGSEND = YES; 259 | GCC_C_LANGUAGE_STANDARD = gnu99; 260 | GCC_NO_COMMON_BLOCKS = YES; 261 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 262 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 263 | GCC_WARN_UNDECLARED_SELECTOR = YES; 264 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 265 | GCC_WARN_UNUSED_FUNCTION = YES; 266 | GCC_WARN_UNUSED_VARIABLE = YES; 267 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 268 | MTL_ENABLE_DEBUG_INFO = NO; 269 | ONLY_ACTIVE_ARCH = NO; 270 | SDKROOT = iphoneos; 271 | TARGETED_DEVICE_FAMILY = "1,2"; 272 | VALIDATE_PRODUCT = YES; 273 | VERSIONING_SYSTEM = "apple-generic"; 274 | VERSION_INFO_PREFIX = ""; 275 | }; 276 | name = Release; 277 | }; 278 | 709EB16E1E25DC7B00342CB1 /* Debug */ = { 279 | isa = XCBuildConfiguration; 280 | buildSettings = { 281 | CODE_SIGN_IDENTITY = ""; 282 | DEFINES_MODULE = YES; 283 | DEVELOPMENT_TEAM = Z25J3BA353; 284 | DYLIB_COMPATIBILITY_VERSION = 1; 285 | DYLIB_CURRENT_VERSION = 1; 286 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 287 | INFOPLIST_FILE = STQRCodeController/Info.plist; 288 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 289 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 290 | MACH_O_TYPE = staticlib; 291 | PRODUCT_BUNDLE_IDENTIFIER = com.st.cn.st; 292 | PRODUCT_NAME = "$(TARGET_NAME)"; 293 | SKIP_INSTALL = YES; 294 | }; 295 | name = Debug; 296 | }; 297 | 709EB16F1E25DC7B00342CB1 /* Release */ = { 298 | isa = XCBuildConfiguration; 299 | buildSettings = { 300 | CODE_SIGN_IDENTITY = ""; 301 | DEFINES_MODULE = YES; 302 | DEVELOPMENT_TEAM = Z25J3BA353; 303 | DYLIB_COMPATIBILITY_VERSION = 1; 304 | DYLIB_CURRENT_VERSION = 1; 305 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 306 | INFOPLIST_FILE = STQRCodeController/Info.plist; 307 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 308 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 309 | MACH_O_TYPE = staticlib; 310 | PRODUCT_BUNDLE_IDENTIFIER = com.st.cn.st; 311 | PRODUCT_NAME = "$(TARGET_NAME)"; 312 | SKIP_INSTALL = YES; 313 | }; 314 | name = Release; 315 | }; 316 | /* End XCBuildConfiguration section */ 317 | 318 | /* Begin XCConfigurationList section */ 319 | 709EB15F1E25DC7B00342CB1 /* Build configuration list for PBXProject "STQRCodeController" */ = { 320 | isa = XCConfigurationList; 321 | buildConfigurations = ( 322 | 709EB16B1E25DC7B00342CB1 /* Debug */, 323 | 709EB16C1E25DC7B00342CB1 /* Release */, 324 | ); 325 | defaultConfigurationIsVisible = 0; 326 | defaultConfigurationName = Release; 327 | }; 328 | 709EB16D1E25DC7B00342CB1 /* Build configuration list for PBXNativeTarget "STQRCodeController" */ = { 329 | isa = XCConfigurationList; 330 | buildConfigurations = ( 331 | 709EB16E1E25DC7B00342CB1 /* Debug */, 332 | 709EB16F1E25DC7B00342CB1 /* Release */, 333 | ); 334 | defaultConfigurationIsVisible = 0; 335 | defaultConfigurationName = Release; 336 | }; 337 | /* End XCConfigurationList section */ 338 | }; 339 | rootObject = 709EB15C1E25DC7B00342CB1 /* Project object */; 340 | } 341 | -------------------------------------------------------------------------------- /STQRCodeController.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /STQRCodeController.xcodeproj/xcshareddata/xcschemes/STQRCodeController.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /STQRCodeController.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 12 | 13 | 15 | 16 | 18 | 19 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /STQRCodeController/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /STQRCodeController/NSBundle+STQRCodeController.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSBundle+STQRCodeController.h 3 | // STQRCodeController 4 | // 5 | // Created by ST on 16/11/29. 6 | // Copyright © 2016年 ST. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface NSBundle (STQRCodeController) 13 | 14 | + (instancetype)st_qrcodeControllerBundle; 15 | + (UIImage *)st_qrcodeControllerImageWithName:(NSString *)name; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /STQRCodeController/NSBundle+STQRCodeController.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSBundle+STQRCodeController.m 3 | // STQRCodeController 4 | // 5 | // Created by ST on 16/11/29. 6 | // Copyright © 2016年 ST. All rights reserved. 7 | // 8 | 9 | #import "NSBundle+STQRCodeController.h" 10 | #import "STQRCodeController.h" 11 | 12 | @implementation NSBundle (STQRCodeController) 13 | 14 | + (instancetype)st_qrcodeControllerBundle 15 | { 16 | static NSBundle *bundle = nil; 17 | bundle = [NSBundle bundleWithPath:[[NSBundle bundleForClass:[STQRCodeController class]] pathForResource:@"STQRCodeController" ofType:@"bundle"]]; 18 | return bundle; 19 | } 20 | 21 | + (UIImage *)st_qrcodeControllerImageWithName:(NSString *)name 22 | { 23 | static UIImage *image = nil; 24 | image = [[UIImage imageWithContentsOfFile:[[self st_qrcodeControllerBundle] pathForResource:name ofType:@"png"]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; 25 | return image; 26 | } 27 | @end 28 | -------------------------------------------------------------------------------- /STQRCodeController/STQRCodeAlert.h: -------------------------------------------------------------------------------- 1 | // 2 | // STQRCodeAlert.h 3 | // STQRCodeController 4 | // 5 | // Created by ST on 16/11/28. 6 | // Copyright © 2016年 ST. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface STQRCodeAlert : UIView 12 | + (void)showWithTitle:(NSString *)title; 13 | @end 14 | -------------------------------------------------------------------------------- /STQRCodeController/STQRCodeAlert.m: -------------------------------------------------------------------------------- 1 | // 2 | // STQRCodeAlert.m 3 | // STQRCodeController 4 | // 5 | // Created by ST on 16/11/28. 6 | // Copyright © 2016年 ST. All rights reserved. 7 | // 8 | 9 | #import "STQRCodeAlert.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface STQRCodeAlert () 14 | /** 1.文本框 */ 15 | @property(nonatomic, strong)UILabel *labelTitle ; 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | 20 | @implementation STQRCodeAlert 21 | 22 | #pragma mark - --- 1.init 生命周期 --- 23 | 24 | - (instancetype)init 25 | { 26 | self = [super init]; 27 | if (self) { 28 | self.bounds = [UIScreen mainScreen].bounds; 29 | self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 30 | [self addSubview:self.labelTitle]; 31 | } 32 | return self; 33 | } 34 | 35 | - (void)layoutSubviews 36 | { 37 | [super layoutSubviews]; 38 | CGRect bounds = [UIScreen mainScreen].bounds; 39 | [self.labelTitle setCenter:CGPointMake(CGRectGetWidth(bounds)/2, CGRectGetHeight(bounds)/2)]; 40 | } 41 | 42 | 43 | #pragma mark - --- 2.delegate 视图委托 --- 44 | 45 | #pragma mark - --- 3.event response 事件相应 --- 46 | 47 | #pragma mark - --- 4.private methods 私有方法 --- 48 | - (void)show 49 | { 50 | [self.labelTitle.layer setOpacity:0]; 51 | [[UIApplication sharedApplication].keyWindow addSubview:self]; 52 | [self setCenter:[UIApplication sharedApplication].keyWindow.center]; 53 | [[UIApplication sharedApplication].keyWindow bringSubviewToFront:self]; 54 | [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{ 55 | [self.labelTitle.layer setOpacity:1.0]; 56 | } completion:^(BOOL finished) { 57 | [self performSelector:@selector(remove) withObject:self afterDelay:1]; 58 | }]; 59 | } 60 | 61 | - (void)remove 62 | { 63 | [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{ 64 | [self.labelTitle.layer setOpacity:0.0]; 65 | } completion:^(BOOL finished) { 66 | [self removeFromSuperview]; 67 | }]; 68 | } 69 | 70 | #pragma mark - --- 5.setters 属性 --- 71 | 72 | + (void)showWithTitle:(NSString *)title 73 | { 74 | STQRCodeAlert *alertView = [[STQRCodeAlert alloc]init]; 75 | [alertView.labelTitle setText:title]; 76 | [alertView.labelTitle sizeToFit]; 77 | CGSize size = alertView.labelTitle.frame.size; 78 | alertView.labelTitle.frame = CGRectMake(0, 0, size.width + 12, size.height+16); 79 | [alertView show]; 80 | } 81 | #pragma mark - --- 6.getters 属性 —-- 82 | 83 | - (UILabel *)labelTitle 84 | { 85 | if (!_labelTitle) { 86 | _labelTitle = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 200, 0)]; 87 | [_labelTitle setTextColor:[UIColor whiteColor]]; 88 | [_labelTitle setTextAlignment:NSTextAlignmentCenter]; 89 | [_labelTitle setBackgroundColor:[UIColor colorWithWhite:0 alpha:0.7]]; 90 | [_labelTitle setFont:[UIFont systemFontOfSize:15]]; 91 | [_labelTitle.layer setCornerRadius:4]; 92 | [_labelTitle setNumberOfLines:0]; 93 | [_labelTitle.layer setMasksToBounds:YES]; 94 | } 95 | return _labelTitle; 96 | } 97 | @end 98 | 99 | -------------------------------------------------------------------------------- /STQRCodeController/STQRCodeConst.h: -------------------------------------------------------------------------------- 1 | // 2 | // STQRCodeConst.h 3 | // STQRCodeController 4 | // 5 | // Created by ST on 16/11/28. 6 | // Copyright © 2016年 ST. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #define ST_QRCODE_ScreenWidth CGRectGetWidth([UIScreen mainScreen].bounds) 12 | #define ST_QRCODE_ScreenHeight CGRectGetHeight([UIScreen mainScreen].bounds) 13 | #define ST_QRCODE_WidthRate ST_QRCODE_ScreenWidth/320 14 | 15 | -------------------------------------------------------------------------------- /STQRCodeController/STQRCodeConst.m: -------------------------------------------------------------------------------- 1 | // 2 | // STQRCodeConst.m 3 | // STQRCodeController 4 | // 5 | // Created by ST on 16/11/28. 6 | // Copyright © 2016年 ST. All rights reserved. 7 | // 8 | 9 | #import "STQRCodeConst.h" 10 | 11 | 12 | -------------------------------------------------------------------------------- /STQRCodeController/STQRCodeController.bundle/st_lightNormal@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/szlsay/STQRCodeController/1c461319c1361f0de71b85aa2b9c2ae538f38ad3/STQRCodeController/STQRCodeController.bundle/st_lightNormal@2x.png -------------------------------------------------------------------------------- /STQRCodeController/STQRCodeController.bundle/st_lightSelect@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/szlsay/STQRCodeController/1c461319c1361f0de71b85aa2b9c2ae538f38ad3/STQRCodeController/STQRCodeController.bundle/st_lightSelect@2x.png -------------------------------------------------------------------------------- /STQRCodeController/STQRCodeController.bundle/st_noticeMusic.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/szlsay/STQRCodeController/1c461319c1361f0de71b85aa2b9c2ae538f38ad3/STQRCodeController/STQRCodeController.bundle/st_noticeMusic.wav -------------------------------------------------------------------------------- /STQRCodeController/STQRCodeController.bundle/st_scanBackground@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/szlsay/STQRCodeController/1c461319c1361f0de71b85aa2b9c2ae538f38ad3/STQRCodeController/STQRCodeController.bundle/st_scanBackground@2x.png -------------------------------------------------------------------------------- /STQRCodeController/STQRCodeController.bundle/st_scanLine@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/szlsay/STQRCodeController/1c461319c1361f0de71b85aa2b9c2ae538f38ad3/STQRCodeController/STQRCodeController.bundle/st_scanLine@2x.png -------------------------------------------------------------------------------- /STQRCodeController/STQRCodeController.h: -------------------------------------------------------------------------------- 1 | // 2 | // STQRCodeController.h 3 | // STQRCodeController 4 | // 5 | // Created by ST on 16/11/28. 6 | // Copyright © 2016年 ST. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | typedef NS_ENUM(NSUInteger, STQRCodeResultType) { 14 | STQRCodeResultTypeSuccess = 0, // 1.成功获取图片中的二维码信息 15 | STQRCodeResultTypeNoInfo = 1, // 2.识别的图片没有二维码信息 16 | STQRCodeResultTypeError = 2 // 3.其他错误 17 | }; 18 | 19 | @class STQRCodeController; 20 | 21 | @protocol STQRCodeControllerDelegate 22 | - (void)qrcodeController:(STQRCodeController *)qrcodeController readerScanResult:(NSString *)readerScanResult type:(STQRCodeResultType)resultType; 23 | @end 24 | 25 | @interface STQRCodeController : UIViewController 26 | @property(nonatomic, weak)iddelegate; 27 | // 点击控制器返回事件 与 成功控制器返回事件 28 | - (void)backButtonEvent; 29 | - (void)backSuccessEvent; 30 | @end 31 | 32 | NS_ASSUME_NONNULL_END 33 | -------------------------------------------------------------------------------- /STQRCodeController/STQRCodeController.m: -------------------------------------------------------------------------------- 1 | // 2 | // STQRCodeController.m 3 | // STQRCodeController 4 | // 5 | // Created by ST on 16/11/28. 6 | // Copyright © 2016年 ST. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | #import "STQRCodeController.h" 13 | #import "STQRCodeReaderView.h" 14 | #import "STQRCodeAlert.h" 15 | 16 | #import "NSBundle+STQRCodeController.h" 17 | #import "STQRCodeConst.h" 18 | @interface STQRCodeController (){ 19 | // 1.记录之前的状态 20 | UIBarStyle _originBarStyle; 21 | } 22 | /** 1.读取二维码界面 */ 23 | @property(nonatomic, strong)STQRCodeReaderView *readview; 24 | /** 2.图片探测器 */ 25 | @property(nonatomic, strong)CIDetector *detector; 26 | /** 4.定时器 */ 27 | @property(nonatomic, strong)NSTimer *timer ; 28 | @end 29 | 30 | @implementation STQRCodeController 31 | 32 | #pragma mark - --- 1.init 生命周期 --- 33 | 34 | - (void)viewDidLoad { 35 | [super viewDidLoad]; 36 | 37 | // 1.设置标题和背景色 38 | self.title = @"扫描"; 39 | self.view.backgroundColor = [UIColor whiteColor]; 40 | 41 | // 2.设置UIBarButtonItem, iOS8系统之后才支持本地扫描 42 | UIBarButtonItem * rightItem = [[UIBarButtonItem alloc]initWithTitle:@"相册" style:UIBarButtonItemStyleDone target:self action:@selector(alumbEvent)]; 43 | self.navigationItem.rightBarButtonItem = rightItem; 44 | 45 | UIBarButtonItem * leftItem = [[UIBarButtonItem alloc]initWithTitle:@"返回" style:UIBarButtonItemStyleDone target:self action:@selector(backButtonEvent)]; 46 | self.navigationItem.leftBarButtonItem = leftItem; 47 | 48 | // self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"返回" style:UIBarButtonItemStylePlain target:self action:@selector(backButtonEvent)]; 49 | 50 | [self.view addSubview:self.readview]; 51 | 52 | // 3.添加进入前后台的事件监控 53 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willEnterForeground) name:UIApplicationWillEnterForegroundNotification object:nil]; 54 | } 55 | 56 | - (void)viewWillAppear:(BOOL)animated 57 | { 58 | [super viewWillAppear:animated]; 59 | 60 | _originBarStyle = self.navigationController.navigationBar.barStyle; 61 | 62 | [self.navigationController.navigationBar setBarStyle:UIBarStyleBlack]; 63 | [self.navigationController.navigationBar setTintColor:[UIColor whiteColor]]; 64 | } 65 | 66 | - (void)viewDidAppear:(BOOL)animated 67 | { 68 | [super viewDidAppear:animated]; 69 | if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) { 70 | self.navigationController.interactivePopGestureRecognizer.delegate = nil; 71 | self.navigationController.interactivePopGestureRecognizer.enabled = YES; 72 | } 73 | [self authorizationStatus]; 74 | 75 | AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 76 | // 4.添加闪关灯的监听事件 77 | if (device.hasFlash) { 78 | [device addObserver:self forKeyPath:@"torchMode" options:NSKeyValueObservingOptionNew context:nil]; 79 | } 80 | } 81 | 82 | - (void)authorizationStatus{ 83 | NSString *mediaType = AVMediaTypeVideo; 84 | AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:mediaType]; 85 | if (authStatus == AVAuthorizationStatusAuthorized) { 86 | [self.readview startScan]; 87 | }else { 88 | [STQRCodeAlert showWithTitle:@"请在设置中开启摄像头权限"]; 89 | [self.readview stopScan]; 90 | self.timer = [NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:@selector(observeAuthrizationStatusChange) userInfo:nil repeats:YES]; 91 | } 92 | } 93 | 94 | - (void)viewWillDisappear:(BOOL)animated 95 | { 96 | [super viewWillDisappear:animated]; 97 | if (self.timer) { 98 | [self.timer invalidate]; 99 | self.timer = nil; 100 | } 101 | [self.readview stopScan]; 102 | 103 | AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 104 | if (device.hasFlash) { 105 | [device removeObserver:self forKeyPath:@"torchMode"]; 106 | [self.readview setTurnOn:NO]; 107 | } 108 | 109 | [self.navigationController.navigationBar setBarStyle:_originBarStyle]; 110 | } 111 | 112 | - (void)dealloc 113 | { 114 | [[NSNotificationCenter defaultCenter]removeObserver:self name:UIApplicationWillEnterForegroundNotification object:nil]; 115 | } 116 | 117 | #pragma mark - --- 2.delegate 视图委托 --- 118 | #pragma mark - --- UIImagePickerController Delegate 119 | - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info 120 | { 121 | // 1.获取图片信息 122 | UIImage *image = [info objectForKey:UIImagePickerControllerEditedImage]; 123 | if (!image){ 124 | image = [info objectForKey:UIImagePickerControllerOriginalImage]; 125 | } 126 | 127 | // 2.退出图片控制器 128 | [picker dismissViewControllerAnimated:YES completion:^{ 129 | 130 | [[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleLightContent]; 131 | 132 | NSArray *features = [self.detector featuresInImage:[CIImage imageWithCGImage:image.CGImage]]; 133 | if (features.count) { // 1.识别到二维码 134 | 135 | // 1.播放提示音 136 | [self playSystemSound]; 137 | 138 | // 2.显示扫描结果信息 139 | CIQRCodeFeature *feature = [features objectAtIndex:0]; 140 | // [STQRCodeAlert showWithTitle:feature.messageString]; 141 | 142 | if ([self.delegate respondsToSelector:@selector(qrcodeController:readerScanResult:type:)]) { 143 | [self.delegate qrcodeController:self readerScanResult:feature.messageString type:STQRCodeResultTypeSuccess]; 144 | [self backSuccessEvent]; 145 | } 146 | }else { 147 | [STQRCodeAlert showWithTitle:@"没有识别到二维码信息\n请重新选择图片"]; 148 | if ([self.delegate respondsToSelector:@selector(qrcodeController:readerScanResult:type:)]) { 149 | [self.delegate qrcodeController:self readerScanResult:@"" type:STQRCodeResultTypeNoInfo]; 150 | // [self backEvent]; 151 | } 152 | } 153 | }]; 154 | } 155 | 156 | - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker 157 | { 158 | [picker dismissViewControllerAnimated:YES completion:^{ 159 | [[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleLightContent]; 160 | }]; 161 | } 162 | 163 | #pragma mark - --- STQRCodeReaderView Delegate 164 | 165 | - (void)qrcodeReaderView:(STQRCodeReaderView *)qrcodeReaderView readerScanResult:(NSString *)readerScanResult 166 | { 167 | // 1.播放提示音 168 | [self playSystemSound]; 169 | 170 | // 2.显示扫描结果信息 171 | // [STQRCodeAlert showWithTitle:readerScanResult]; 172 | 173 | if ([self.delegate respondsToSelector:@selector(qrcodeController:readerScanResult:type:)]) { 174 | [self.delegate qrcodeController:self readerScanResult:readerScanResult type:STQRCodeResultTypeSuccess]; 175 | [self backSuccessEvent]; 176 | }else { 177 | // 重新扫描 178 | // [self.readview performSelector:@selector(startScan) withObject:nil afterDelay:2]; 179 | } 180 | } 181 | 182 | 183 | #pragma mark - --- 3.event response 事件相应 --- 184 | // 1.点击返回操作 185 | - (void)backButtonEvent 186 | { 187 | [self.navigationController popViewControllerAnimated:YES]; 188 | [self dismissViewControllerAnimated:YES completion:^{}]; 189 | } 190 | 191 | // 2.成功获取信息返回操作 192 | - (void)backSuccessEvent{ 193 | [self backButtonEvent]; 194 | } 195 | 196 | // 3.相册事件 197 | - (void)alumbEvent 198 | { 199 | if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) { //判断设备是否支持相册 200 | [STQRCodeAlert showWithTitle:@"未开启访问相册权限,请在设置中开始"]; 201 | return; 202 | } 203 | 204 | UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init]; 205 | imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; 206 | imagePickerController.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeSavedPhotosAlbum]; 207 | imagePickerController.allowsEditing = YES; 208 | imagePickerController.delegate = self; 209 | [self presentViewController:imagePickerController animated:YES completion:^{ 210 | [[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleDefault]; 211 | }]; 212 | } 213 | 214 | // 4.播放提示音 215 | - (void)playSystemSound{ 216 | SystemSoundID soundID; 217 | NSString *strSoundFile = [[NSBundle st_qrcodeControllerBundle] pathForResource:@"st_noticeMusic" ofType:@"wav"]; 218 | AudioServicesCreateSystemSoundID((__bridge CFURLRef)[NSURL fileURLWithPath:strSoundFile],&soundID); 219 | AudioServicesPlaySystemSound(soundID); 220 | } 221 | 222 | #pragma mark - --- 4.private methods 私有方法 --- 223 | 224 | // 1.监听摄像头权限 225 | - (void)observeAuthrizationStatusChange{ 226 | NSString *mediaType = AVMediaTypeVideo; 227 | AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:mediaType]; 228 | if (authStatus == AVAuthorizationStatusAuthorized) { 229 | [self.timer invalidate]; 230 | self.timer = nil; 231 | [self.readview startScan]; 232 | } 233 | } 234 | 235 | // 2.监听系统闪关灯的是否打开 236 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 237 | { 238 | if ([@"torchMode" isEqualToString:keyPath]) { 239 | if ([@"1" isEqualToString:[NSString stringWithFormat:@"%@", change[@"new"]]]) { 240 | [self.readview setTurnOn:YES]; 241 | }else{ 242 | [self.readview setTurnOn:NO]; 243 | } 244 | } 245 | } 246 | 247 | // 3.进入前台,重新刷新扫描 248 | - (void)willEnterForeground 249 | { 250 | if (self.readview) { 251 | [self.readview stopScan]; 252 | [self performSelector:@selector(authorizationStatus) withObject:self afterDelay:0.1]; 253 | } 254 | } 255 | 256 | 257 | - (BOOL)shouldAutorotate 258 | { 259 | return NO; 260 | } 261 | 262 | - (UIInterfaceOrientationMask)supportedInterfaceOrientations { 263 | return UIInterfaceOrientationMaskPortrait; 264 | } 265 | 266 | - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { 267 | return UIInterfaceOrientationPortrait; 268 | } 269 | 270 | #pragma mark - --- 5.setters 属性 --- 271 | 272 | #pragma mark - --- 6.getters 属性 —-- 273 | 274 | - (STQRCodeReaderView *)readview 275 | { 276 | if (!_readview) { 277 | _readview = [[STQRCodeReaderView alloc]init]; 278 | _readview.delegate = self; 279 | } 280 | return _readview; 281 | } 282 | 283 | - (CIDetector *)detector 284 | { 285 | if (!_detector) { 286 | _detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{ CIDetectorAccuracy : CIDetectorAccuracyHigh }]; 287 | } 288 | return _detector; 289 | } 290 | @end 291 | 292 | -------------------------------------------------------------------------------- /STQRCodeController/STQRCodeReaderView.h: -------------------------------------------------------------------------------- 1 | // 2 | // STQRCodeReaderView.h 3 | // STQRCodeController 4 | // 5 | // Created by ST on 16/11/28. 6 | // Copyright © 2016年 ST. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @class STQRCodeReaderView; 14 | 15 | @protocol STQRCodeReaderViewDelegate 16 | - (void)qrcodeReaderView:(STQRCodeReaderView *)qrcodeReaderView readerScanResult:(NSString *)readerScanResult; 17 | @end 18 | 19 | @interface STQRCodeReaderView : UIView 20 | 21 | @property (nonatomic, weak) id delegate; 22 | 23 | /** 开启扫描 */ 24 | - (void)startScan; 25 | /** 关闭扫描 */ 26 | - (void)stopScan; 27 | /** 1.设置闪关灯开始 */ 28 | @property(nonatomic, assign)BOOL turnOn; 29 | /** 2.是否开启手机环境光线检测,default is YES */ 30 | @property(nonatomic, assign)BOOL openDetection; 31 | @end 32 | NS_ASSUME_NONNULL_END 33 | -------------------------------------------------------------------------------- /STQRCodeController/STQRCodeReaderView.m: -------------------------------------------------------------------------------- 1 | // 2 | // STQRCodeReaderView.m 3 | // STQRCodeController 4 | // 5 | // Created by ST on 16/11/28. 6 | // Copyright © 2016年 ST. All rights reserved. 7 | // 8 | 9 | #import "STQRCodeReaderView.h" 10 | #import 11 | #import "STQRCodeConst.h" 12 | #import "NSBundle+STQRCodeController.h" 13 | #import 14 | 15 | @interface STQRCodeReaderView () 16 | /** 1.中间扫描图片 */ 17 | @property(nonatomic, strong)UIImageView *imageScanZone; 18 | /** 2.扫描的尺寸 */ 19 | @property(nonatomic, assign)CGRect rectScanZone; 20 | /** 3.获取会话 */ 21 | @property(nonatomic, strong)AVCaptureSession *captureSession; 22 | /** 4.遮罩视图 */ 23 | @property(nonatomic, strong)UIView *viewMask; 24 | /** 5.开启闪光灯 */ 25 | @property(nonatomic, strong)UIButton *buttonTurn; 26 | /** 6.移动的图片 */ 27 | @property(nonatomic, strong)UIImageView *imageMove; 28 | /** 7.提示语 */ 29 | @property(nonatomic, strong)UILabel *labelAlert; 30 | /** 8.获取视频输出 */ 31 | @property(nonatomic, strong)AVCaptureVideoDataOutput *captureVideoDataOutput; 32 | 33 | /** 开始扫描动画 */ 34 | - (void)startAnimation; 35 | 36 | /** 关闭扫描动画 */ 37 | - (void)stopAnimation; 38 | 39 | @end 40 | 41 | 42 | @implementation STQRCodeReaderView 43 | 44 | #pragma mark - --- 1.init 生命周期 --- 45 | 46 | - (instancetype)init 47 | { 48 | self = [super init]; 49 | if (self) { 50 | [self setupDefault]; 51 | } 52 | return self; 53 | } 54 | 55 | - (instancetype)initWithFrame:(CGRect)frame 56 | { 57 | self = [super initWithFrame:frame]; 58 | if (self) { 59 | [self setupDefault]; 60 | } 61 | return self; 62 | } 63 | 64 | - (void)layoutSubviews 65 | { 66 | [super layoutSubviews]; 67 | self.imageScanZone.frame = self.rectScanZone; 68 | self.buttonTurn.center = CGPointMake(self.imageScanZone.center.x, CGRectGetMaxY(self.imageScanZone.frame) + 100); 69 | self.labelAlert.center = CGPointMake(self.imageScanZone.center.x, CGRectGetMaxY(self.imageScanZone.frame) + 20); 70 | } 71 | 72 | - (void)setupDefault 73 | { 74 | // 1.基本属性 75 | [self setFrame:CGRectMake(0, 0, ST_QRCODE_ScreenWidth, ST_QRCODE_ScreenHeight)]; 76 | [self setBackgroundColor:[UIColor blackColor]]; 77 | [self addSubview:self.viewMask]; 78 | [self addSubview:self.imageMove]; 79 | [self addSubview:self.imageScanZone]; 80 | [self addSubview:self.buttonTurn]; 81 | [self addSubview:self.labelAlert]; 82 | 83 | _openDetection = YES; 84 | 85 | // 2.采样的区域 86 | AVCaptureVideoPreviewLayer * layer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession]; 87 | layer.videoGravity=AVLayerVideoGravityResizeAspectFill; 88 | layer.frame=self.layer.bounds; 89 | [self.layer insertSublayer:layer atIndex:0]; 90 | 91 | // 3.如果不支持闪光灯,不显示闪光灯按钮 92 | AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 93 | self.buttonTurn.hidden = !device.hasTorch; 94 | } 95 | 96 | #pragma mark - --- 2.delegate 视图委托 --- 97 | 98 | 99 | #pragma mark - AVCaptureVideoDataOutputSampleBufferDelegate 100 | - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection{ 101 | /** 102 | * 1.获取CMSampleBuffer的数目,0的话没有数据,发生错误了. 103 | * 2.CMSampleBuffer 无效 104 | * 3.CMSampleBuffer 数据没准备好 105 | */ 106 | if (self.openDetection) { 107 | if ((CMSampleBufferGetNumSamples(sampleBuffer) == 0) || !CMSampleBufferIsValid(sampleBuffer) || !CMSampleBufferDataIsReady(sampleBuffer)) { 108 | //为无效的 CMSampleBuffer ,没有必要进行后面的逻辑! 109 | return; 110 | } 111 | CFDictionaryRef metadataDict = CMCopyDictionaryOfAttachments(NULL, 112 | sampleBuffer, kCMAttachmentMode_ShouldPropagate); 113 | NSDictionary *metadata = [[NSMutableDictionary alloc] 114 | initWithDictionary:(__bridge NSDictionary*)metadataDict]; 115 | CFRelease(metadataDict); 116 | NSDictionary *exifMetadata = [[metadata 117 | objectForKey:(NSString *)kCGImagePropertyExifDictionary] mutableCopy]; 118 | float brightnessValue = [[exifMetadata 119 | objectForKey:(NSString *)kCGImagePropertyExifBrightnessValue] floatValue]; 120 | NSLog(@"%s %f", __FUNCTION__, brightnessValue); 121 | if (brightnessValue <= 0) { 122 | if (!self.buttonTurn.selected) { 123 | self.openDetection = NO; 124 | dispatch_async(dispatch_get_main_queue(), ^{ 125 | [self turnTorchEvent:self.buttonTurn]; 126 | [self setTurnOn:YES]; 127 | // [self.captureSession removeOutput:self.captureVideoDataOutput]; 128 | }); 129 | 130 | } 131 | } 132 | } 133 | } 134 | 135 | - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection 136 | { 137 | if (metadataObjects && metadataObjects.count > 0 ) { 138 | AVMetadataMachineReadableCodeObject * metadataObject = metadataObjects[0]; 139 | //输出扫描字符串 140 | if (self.delegate && [self.delegate respondsToSelector:@selector(qrcodeReaderView:readerScanResult:)]) { 141 | [self.delegate qrcodeReaderView:self readerScanResult:metadataObject.stringValue]; 142 | } 143 | } 144 | 145 | [self stopScan]; 146 | } 147 | 148 | #pragma mark - --- 3.event response 事件相应 --- 149 | 150 | - (void)startScan 151 | { 152 | [self.captureSession startRunning]; 153 | [self startAnimation]; 154 | } 155 | 156 | - (void)stopScan 157 | { 158 | [self.captureSession stopRunning]; 159 | [self stopAnimation]; 160 | } 161 | 162 | - (void)turnTorchEvent:(UIButton *)button 163 | { 164 | AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 165 | if ([device hasTorch] && [device hasFlash]){ 166 | [device lockForConfiguration:nil]; 167 | if (!button.selected) { 168 | [device setTorchMode:AVCaptureTorchModeOn]; 169 | [device setFlashMode:AVCaptureFlashModeOn]; 170 | } else { 171 | [device setTorchMode:AVCaptureTorchModeOff]; 172 | [device setFlashMode:AVCaptureFlashModeOff]; 173 | } 174 | [device unlockForConfiguration]; 175 | } 176 | } 177 | 178 | - (void)startAnimation 179 | { 180 | CGFloat viewW = 200*ST_QRCODE_WidthRate; 181 | CGFloat viewH = 3; 182 | CGFloat viewX = (ST_QRCODE_ScreenWidth - viewW)/2; 183 | __block CGFloat viewY = (ST_QRCODE_ScreenHeight- viewW)/2; 184 | __block CGRect rect = CGRectMake(viewX, viewY, viewW, viewH); 185 | [UIView animateWithDuration:1.5 delay:0 options:UIViewAnimationOptionRepeat animations:^{ 186 | viewY = (ST_QRCODE_ScreenHeight- viewW)/2 + 200*ST_QRCODE_WidthRate - 5; 187 | rect = CGRectMake(viewX, viewY, viewW, viewH); 188 | self.imageMove.frame = rect; 189 | } completion:^(BOOL finished) { 190 | viewY = (ST_QRCODE_ScreenHeight- viewW)/2; 191 | rect = CGRectMake(viewX, viewY, viewW, viewH); 192 | self.imageMove.frame = rect; 193 | }]; 194 | } 195 | 196 | - (void)stopAnimation 197 | { 198 | CGFloat viewW = 200*ST_QRCODE_WidthRate; 199 | CGFloat viewH = 3; 200 | CGFloat viewX = (ST_QRCODE_ScreenWidth - viewW)/2; 201 | __block CGFloat viewY = (ST_QRCODE_ScreenHeight- viewW)/2; 202 | __block CGRect rect = CGRectMake(viewX, viewY, viewW, viewH); 203 | [UIView animateWithDuration:0.01 animations:^{ 204 | self.imageMove.frame = rect; 205 | }]; 206 | } 207 | #pragma mark - --- 4.private methods 私有方法 --- 208 | 209 | -(CGRect)getScanCrop:(CGRect)rect readerViewBounds:(CGRect)readerViewBounds 210 | { 211 | CGFloat x,y,width,height; 212 | x = (CGRectGetHeight(readerViewBounds)-CGRectGetHeight(rect))/2/CGRectGetHeight(readerViewBounds); 213 | y = (CGRectGetWidth(readerViewBounds)-CGRectGetWidth(rect))/2/CGRectGetWidth(readerViewBounds); 214 | width = CGRectGetHeight(rect)/CGRectGetHeight(readerViewBounds); 215 | height = CGRectGetWidth(rect)/CGRectGetWidth(readerViewBounds); 216 | return CGRectMake(x, y, width, height); 217 | } 218 | #pragma mark - --- 5.setters 属性 --- 219 | 220 | - (void)setTurnOn:(BOOL)turnOn 221 | { 222 | _turnOn = turnOn; 223 | self.buttonTurn.selected = turnOn; 224 | } 225 | 226 | #pragma mark - --- 6.getters 属性 —-- 227 | 228 | - (UIImageView *)imageScanZone{ 229 | if (!_imageScanZone) { 230 | _imageScanZone = [[UIImageView alloc]initWithImage:[NSBundle st_qrcodeControllerImageWithName:@"st_scanBackground@2x"]]; 231 | } 232 | return _imageScanZone; 233 | } 234 | 235 | - (CGRect)rectScanZone 236 | { 237 | return CGRectMake(60*ST_QRCODE_WidthRate, (ST_QRCODE_ScreenHeight-200*ST_QRCODE_WidthRate)/2, 200*ST_QRCODE_WidthRate, 200*ST_QRCODE_WidthRate); 238 | } 239 | 240 | - (AVCaptureSession *)captureSession 241 | { 242 | if (!_captureSession) { 243 | //获取摄像设备 244 | AVCaptureDevice * device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 245 | //创建输入流 246 | AVCaptureDeviceInput * input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil]; 247 | //创建输出流 248 | AVCaptureMetadataOutput * output = [[AVCaptureMetadataOutput alloc]init]; 249 | //设置代理 在主线程里刷新 250 | [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()]; 251 | CGRect scanCrop=[self getScanCrop:self.rectScanZone readerViewBounds:self.frame]; 252 | output.rectOfInterest = scanCrop; 253 | 254 | //初始化链接对象 255 | _captureSession = [[AVCaptureSession alloc]init]; 256 | //高质量采集率 257 | [_captureSession setSessionPreset:AVCaptureSessionPresetHigh]; 258 | if (input) { 259 | [_captureSession addInput:input]; 260 | } 261 | if (output) { 262 | [_captureSession addOutput:output]; 263 | //设置扫码支持的编码格式(如下设置条形码和二维码兼容) 264 | NSMutableArray *array = [[NSMutableArray alloc] init]; 265 | if ([output.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeQRCode]) { 266 | [array addObject:AVMetadataObjectTypeQRCode]; 267 | } 268 | if ([output.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeEAN13Code]) { 269 | [array addObject:AVMetadataObjectTypeEAN13Code]; 270 | } 271 | if ([output.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeEAN8Code]) { 272 | [array addObject:AVMetadataObjectTypeEAN8Code]; 273 | } 274 | if ([output.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeCode128Code]) { 275 | [array addObject:AVMetadataObjectTypeCode128Code]; 276 | } 277 | output.metadataObjectTypes = array; 278 | } 279 | 280 | 281 | if ([_captureSession canSetSessionPreset:AVCaptureSessionPreset3840x2160]) { 282 | _captureSession.sessionPreset = AVCaptureSessionPreset3840x2160;//4k 283 | }else if ([_captureSession canSetSessionPreset:AVCaptureSessionPreset1920x1080]){ 284 | _captureSession.sessionPreset = AVCaptureSessionPreset1920x1080;//1080P 285 | }else if ([_captureSession canSetSessionPreset:AVCaptureSessionPreset1280x720]){ 286 | _captureSession.sessionPreset = AVCaptureSessionPreset1280x720;//1080P 287 | }else if ([_captureSession canSetSessionPreset:AVCaptureSessionPresetHigh]){ 288 | _captureSession.sessionPreset = AVCaptureSessionPresetHigh;//High 289 | }else{ 290 | //weakSelf.captureSession.sessionPreset = deafault value (AVCaptureSessionPresetHigh) 291 | } 292 | 293 | 294 | //session addOutput 295 | if ([_captureSession canAddOutput:self.captureVideoDataOutput]) { 296 | [_captureSession addOutput:self.captureVideoDataOutput]; 297 | } 298 | 299 | } 300 | return _captureSession; 301 | } 302 | 303 | - (AVCaptureVideoDataOutput *)captureVideoDataOutput{ 304 | if (!_captureVideoDataOutput) { 305 | // 306 | _captureVideoDataOutput = [[AVCaptureVideoDataOutput alloc] init]; 307 | /* 308 | .videoSettings 如果设置为nil , 之后才读取.videoSettings 不会是nil ,而是AVCaptureSession.sessionPreset的值 , 这就表示 以无压缩的格式 接收视频帧 309 | 在iOS上, videoSettings 唯一支持的key 只有kCVPixelBufferPixelFormatTypeKey 310 | value只有3种:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange / kCVPixelFormatType_420YpCbCr8BiPlanarFullRange / kCVPixelFormatType_32BGRA 311 | */ 312 | _captureVideoDataOutput.videoSettings = @{(NSString *)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_32BGRA)}; 313 | //丢弃掉延迟的视频帧,不再传给buffer queue 314 | _captureVideoDataOutput.alwaysDiscardsLateVideoFrames = YES; 315 | 316 | dispatch_queue_t videoDataOutputQueue = dispatch_queue_create("com.CircleLi_VideoDataOutputQueue.www", DISPATCH_QUEUE_SERIAL);//必须是串行队列, 保证视频帧按顺序传递 317 | [_captureVideoDataOutput setSampleBufferDelegate:self queue:videoDataOutputQueue]; 318 | 319 | } 320 | return _captureVideoDataOutput; 321 | } 322 | 323 | - (UIView *)viewMask 324 | { 325 | if (!_viewMask) { 326 | _viewMask = [[UIView alloc]initWithFrame:self.bounds]; 327 | [_viewMask setBackgroundColor:[UIColor blackColor]]; 328 | [_viewMask setAlpha:102.0/255]; 329 | UIBezierPath *path = [UIBezierPath bezierPath]; 330 | [path appendPath:[UIBezierPath bezierPathWithRect:_viewMask.bounds]]; 331 | [path appendPath:[UIBezierPath bezierPathWithRect:self.rectScanZone].bezierPathByReversingPath]; 332 | CAShapeLayer *maskLayer = [CAShapeLayer layer]; 333 | maskLayer.path = path.CGPath; 334 | _viewMask.layer.mask = maskLayer; 335 | } 336 | return _viewMask; 337 | } 338 | 339 | - (UIImageView *)imageMove 340 | { 341 | if (!_imageMove) { 342 | CGFloat viewW = 200*ST_QRCODE_WidthRate; 343 | CGFloat viewH = 3; 344 | CGFloat viewX = (ST_QRCODE_ScreenWidth - viewW)/2; 345 | CGFloat viewY = (ST_QRCODE_ScreenHeight- viewW)/2; 346 | _imageMove = [[UIImageView alloc]initWithFrame:CGRectMake(viewX, viewY, viewW, viewH)]; 347 | _imageMove.image = [NSBundle st_qrcodeControllerImageWithName:@"st_scanLine@2x"]; 348 | } 349 | return _imageMove; 350 | } 351 | 352 | - (UIButton *)buttonTurn 353 | { 354 | if (!_buttonTurn) { 355 | _buttonTurn = [UIButton buttonWithType:UIButtonTypeCustom]; 356 | [_buttonTurn setBackgroundImage:[NSBundle st_qrcodeControllerImageWithName:@"st_lightSelect@2x"] forState:UIControlStateNormal]; 357 | [_buttonTurn setBackgroundImage:[NSBundle st_qrcodeControllerImageWithName:@"st_lightNormal@2x"] forState:UIControlStateSelected]; 358 | [_buttonTurn sizeToFit]; 359 | [_buttonTurn addTarget:self action:@selector(turnTorchEvent:) forControlEvents:UIControlEventTouchUpInside]; 360 | } 361 | return _buttonTurn; 362 | } 363 | 364 | - (UILabel *)labelAlert 365 | { 366 | if (!_labelAlert) { 367 | CGFloat viewW = ST_QRCODE_ScreenWidth; 368 | CGFloat viewH = 17; 369 | CGFloat viewX = 0; 370 | CGFloat viewY = 0; 371 | _labelAlert = [[UILabel alloc]initWithFrame:CGRectMake(viewX, viewY, viewW, viewH)]; 372 | [_labelAlert setText:@"将二维码/条形码放置框内,即开始扫描"]; 373 | [_labelAlert setTextColor:[UIColor whiteColor]]; 374 | [_labelAlert setFont:[UIFont systemFontOfSize:15]]; 375 | [_labelAlert setTextAlignment:NSTextAlignmentCenter]; 376 | } 377 | return _labelAlert; 378 | } 379 | @end 380 | -------------------------------------------------------------------------------- /STQRCodeControllerDemo/STQRCodeControllerDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 7085510C1DFFF43300C243ED /* TestController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7085510B1DFFF43300C243ED /* TestController.m */; }; 11 | 7092D4BC1DED69ED00E9A998 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 7092D4BB1DED69ED00E9A998 /* main.m */; }; 12 | 7092D4BF1DED69ED00E9A998 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7092D4BE1DED69ED00E9A998 /* AppDelegate.m */; }; 13 | 7092D4C71DED69ED00E9A998 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7092D4C61DED69ED00E9A998 /* Assets.xcassets */; }; 14 | 7092D4CA1DED69ED00E9A998 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7092D4C81DED69ED00E9A998 /* LaunchScreen.storyboard */; }; 15 | 70B0DED21EBC61A200837A55 /* NSBundle+STQRCodeController.m in Sources */ = {isa = PBXBuildFile; fileRef = 70B0DEC71EBC61A200837A55 /* NSBundle+STQRCodeController.m */; }; 16 | 70B0DED31EBC61A200837A55 /* STQRCodeAlert.m in Sources */ = {isa = PBXBuildFile; fileRef = 70B0DEC91EBC61A200837A55 /* STQRCodeAlert.m */; }; 17 | 70B0DED41EBC61A200837A55 /* STQRCodeConst.m in Sources */ = {isa = PBXBuildFile; fileRef = 70B0DECB1EBC61A200837A55 /* STQRCodeConst.m */; }; 18 | 70B0DED51EBC61A200837A55 /* STQRCodeController.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 70B0DECC1EBC61A200837A55 /* STQRCodeController.bundle */; }; 19 | 70B0DED61EBC61A200837A55 /* STQRCodeController.m in Sources */ = {isa = PBXBuildFile; fileRef = 70B0DECE1EBC61A200837A55 /* STQRCodeController.m */; }; 20 | 70B0DED71EBC61A200837A55 /* STQRCodeReaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 70B0DED01EBC61A200837A55 /* STQRCodeReaderView.m */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXFileReference section */ 24 | 7085510A1DFFF43300C243ED /* TestController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestController.h; sourceTree = ""; }; 25 | 7085510B1DFFF43300C243ED /* TestController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestController.m; sourceTree = ""; }; 26 | 7092D4B71DED69ED00E9A998 /* STQRCodeControllerDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = STQRCodeControllerDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | 7092D4BB1DED69ED00E9A998 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 28 | 7092D4BD1DED69ED00E9A998 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 29 | 7092D4BE1DED69ED00E9A998 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 30 | 7092D4C61DED69ED00E9A998 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 31 | 7092D4C91DED69ED00E9A998 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 32 | 7092D4CB1DED69ED00E9A998 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 33 | 70B0DEC61EBC61A200837A55 /* NSBundle+STQRCodeController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSBundle+STQRCodeController.h"; sourceTree = ""; }; 34 | 70B0DEC71EBC61A200837A55 /* NSBundle+STQRCodeController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSBundle+STQRCodeController.m"; sourceTree = ""; }; 35 | 70B0DEC81EBC61A200837A55 /* STQRCodeAlert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STQRCodeAlert.h; sourceTree = ""; }; 36 | 70B0DEC91EBC61A200837A55 /* STQRCodeAlert.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STQRCodeAlert.m; sourceTree = ""; }; 37 | 70B0DECA1EBC61A200837A55 /* STQRCodeConst.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STQRCodeConst.h; sourceTree = ""; }; 38 | 70B0DECB1EBC61A200837A55 /* STQRCodeConst.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STQRCodeConst.m; sourceTree = ""; }; 39 | 70B0DECC1EBC61A200837A55 /* STQRCodeController.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = STQRCodeController.bundle; sourceTree = ""; }; 40 | 70B0DECD1EBC61A200837A55 /* STQRCodeController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STQRCodeController.h; sourceTree = ""; }; 41 | 70B0DECE1EBC61A200837A55 /* STQRCodeController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STQRCodeController.m; sourceTree = ""; }; 42 | 70B0DECF1EBC61A200837A55 /* STQRCodeReaderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STQRCodeReaderView.h; sourceTree = ""; }; 43 | 70B0DED01EBC61A200837A55 /* STQRCodeReaderView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STQRCodeReaderView.m; sourceTree = ""; }; 44 | /* End PBXFileReference section */ 45 | 46 | /* Begin PBXFrameworksBuildPhase section */ 47 | 7092D4B41DED69ED00E9A998 /* Frameworks */ = { 48 | isa = PBXFrameworksBuildPhase; 49 | buildActionMask = 2147483647; 50 | files = ( 51 | ); 52 | runOnlyForDeploymentPostprocessing = 0; 53 | }; 54 | /* End PBXFrameworksBuildPhase section */ 55 | 56 | /* Begin PBXGroup section */ 57 | 7092D4AE1DED69ED00E9A998 = { 58 | isa = PBXGroup; 59 | children = ( 60 | 7092D4B91DED69ED00E9A998 /* STQRCodeControllerDemo */, 61 | 7092D4B81DED69ED00E9A998 /* Products */, 62 | ); 63 | sourceTree = ""; 64 | }; 65 | 7092D4B81DED69ED00E9A998 /* Products */ = { 66 | isa = PBXGroup; 67 | children = ( 68 | 7092D4B71DED69ED00E9A998 /* STQRCodeControllerDemo.app */, 69 | ); 70 | name = Products; 71 | sourceTree = ""; 72 | }; 73 | 7092D4B91DED69ED00E9A998 /* STQRCodeControllerDemo */ = { 74 | isa = PBXGroup; 75 | children = ( 76 | 70B0DEC41EBC61A200837A55 /* STQRCodeController */, 77 | 7092D4BD1DED69ED00E9A998 /* AppDelegate.h */, 78 | 7092D4BE1DED69ED00E9A998 /* AppDelegate.m */, 79 | 7085510A1DFFF43300C243ED /* TestController.h */, 80 | 7085510B1DFFF43300C243ED /* TestController.m */, 81 | 7092D4C61DED69ED00E9A998 /* Assets.xcassets */, 82 | 7092D4C81DED69ED00E9A998 /* LaunchScreen.storyboard */, 83 | 7092D4CB1DED69ED00E9A998 /* Info.plist */, 84 | 7092D4BA1DED69ED00E9A998 /* Supporting Files */, 85 | ); 86 | path = STQRCodeControllerDemo; 87 | sourceTree = ""; 88 | }; 89 | 7092D4BA1DED69ED00E9A998 /* Supporting Files */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | 7092D4BB1DED69ED00E9A998 /* main.m */, 93 | ); 94 | name = "Supporting Files"; 95 | sourceTree = ""; 96 | }; 97 | 70B0DEC41EBC61A200837A55 /* STQRCodeController */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | 70B0DEC61EBC61A200837A55 /* NSBundle+STQRCodeController.h */, 101 | 70B0DEC71EBC61A200837A55 /* NSBundle+STQRCodeController.m */, 102 | 70B0DEC81EBC61A200837A55 /* STQRCodeAlert.h */, 103 | 70B0DEC91EBC61A200837A55 /* STQRCodeAlert.m */, 104 | 70B0DECA1EBC61A200837A55 /* STQRCodeConst.h */, 105 | 70B0DECB1EBC61A200837A55 /* STQRCodeConst.m */, 106 | 70B0DECC1EBC61A200837A55 /* STQRCodeController.bundle */, 107 | 70B0DECD1EBC61A200837A55 /* STQRCodeController.h */, 108 | 70B0DECE1EBC61A200837A55 /* STQRCodeController.m */, 109 | 70B0DECF1EBC61A200837A55 /* STQRCodeReaderView.h */, 110 | 70B0DED01EBC61A200837A55 /* STQRCodeReaderView.m */, 111 | ); 112 | name = STQRCodeController; 113 | path = ../../STQRCodeController; 114 | sourceTree = ""; 115 | }; 116 | /* End PBXGroup section */ 117 | 118 | /* Begin PBXNativeTarget section */ 119 | 7092D4B61DED69ED00E9A998 /* STQRCodeControllerDemo */ = { 120 | isa = PBXNativeTarget; 121 | buildConfigurationList = 7092D4CE1DED69ED00E9A998 /* Build configuration list for PBXNativeTarget "STQRCodeControllerDemo" */; 122 | buildPhases = ( 123 | 7092D4B31DED69ED00E9A998 /* Sources */, 124 | 7092D4B41DED69ED00E9A998 /* Frameworks */, 125 | 7092D4B51DED69ED00E9A998 /* Resources */, 126 | ); 127 | buildRules = ( 128 | ); 129 | dependencies = ( 130 | ); 131 | name = STQRCodeControllerDemo; 132 | productName = STQRCodeControllerDemo; 133 | productReference = 7092D4B71DED69ED00E9A998 /* STQRCodeControllerDemo.app */; 134 | productType = "com.apple.product-type.application"; 135 | }; 136 | /* End PBXNativeTarget section */ 137 | 138 | /* Begin PBXProject section */ 139 | 7092D4AF1DED69ED00E9A998 /* Project object */ = { 140 | isa = PBXProject; 141 | attributes = { 142 | LastUpgradeCheck = 0820; 143 | ORGANIZATIONNAME = ST; 144 | TargetAttributes = { 145 | 7092D4B61DED69ED00E9A998 = { 146 | CreatedOnToolsVersion = 8.1; 147 | DevelopmentTeam = Z25J3BA353; 148 | ProvisioningStyle = Automatic; 149 | }; 150 | }; 151 | }; 152 | buildConfigurationList = 7092D4B21DED69ED00E9A998 /* Build configuration list for PBXProject "STQRCodeControllerDemo" */; 153 | compatibilityVersion = "Xcode 3.2"; 154 | developmentRegion = English; 155 | hasScannedForEncodings = 0; 156 | knownRegions = ( 157 | en, 158 | Base, 159 | ); 160 | mainGroup = 7092D4AE1DED69ED00E9A998; 161 | productRefGroup = 7092D4B81DED69ED00E9A998 /* Products */; 162 | projectDirPath = ""; 163 | projectRoot = ""; 164 | targets = ( 165 | 7092D4B61DED69ED00E9A998 /* STQRCodeControllerDemo */, 166 | ); 167 | }; 168 | /* End PBXProject section */ 169 | 170 | /* Begin PBXResourcesBuildPhase section */ 171 | 7092D4B51DED69ED00E9A998 /* Resources */ = { 172 | isa = PBXResourcesBuildPhase; 173 | buildActionMask = 2147483647; 174 | files = ( 175 | 7092D4CA1DED69ED00E9A998 /* LaunchScreen.storyboard in Resources */, 176 | 7092D4C71DED69ED00E9A998 /* Assets.xcassets in Resources */, 177 | 70B0DED51EBC61A200837A55 /* STQRCodeController.bundle in Resources */, 178 | ); 179 | runOnlyForDeploymentPostprocessing = 0; 180 | }; 181 | /* End PBXResourcesBuildPhase section */ 182 | 183 | /* Begin PBXSourcesBuildPhase section */ 184 | 7092D4B31DED69ED00E9A998 /* Sources */ = { 185 | isa = PBXSourcesBuildPhase; 186 | buildActionMask = 2147483647; 187 | files = ( 188 | 70B0DED31EBC61A200837A55 /* STQRCodeAlert.m in Sources */, 189 | 7092D4BF1DED69ED00E9A998 /* AppDelegate.m in Sources */, 190 | 70B0DED71EBC61A200837A55 /* STQRCodeReaderView.m in Sources */, 191 | 70B0DED61EBC61A200837A55 /* STQRCodeController.m in Sources */, 192 | 7092D4BC1DED69ED00E9A998 /* main.m in Sources */, 193 | 7085510C1DFFF43300C243ED /* TestController.m in Sources */, 194 | 70B0DED41EBC61A200837A55 /* STQRCodeConst.m in Sources */, 195 | 70B0DED21EBC61A200837A55 /* NSBundle+STQRCodeController.m in Sources */, 196 | ); 197 | runOnlyForDeploymentPostprocessing = 0; 198 | }; 199 | /* End PBXSourcesBuildPhase section */ 200 | 201 | /* Begin PBXVariantGroup section */ 202 | 7092D4C81DED69ED00E9A998 /* LaunchScreen.storyboard */ = { 203 | isa = PBXVariantGroup; 204 | children = ( 205 | 7092D4C91DED69ED00E9A998 /* Base */, 206 | ); 207 | name = LaunchScreen.storyboard; 208 | sourceTree = ""; 209 | }; 210 | /* End PBXVariantGroup section */ 211 | 212 | /* Begin XCBuildConfiguration section */ 213 | 7092D4CC1DED69ED00E9A998 /* Debug */ = { 214 | isa = XCBuildConfiguration; 215 | buildSettings = { 216 | ALWAYS_SEARCH_USER_PATHS = NO; 217 | CLANG_ANALYZER_NONNULL = YES; 218 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 219 | CLANG_CXX_LIBRARY = "libc++"; 220 | CLANG_ENABLE_MODULES = YES; 221 | CLANG_ENABLE_OBJC_ARC = YES; 222 | CLANG_WARN_BOOL_CONVERSION = YES; 223 | CLANG_WARN_CONSTANT_CONVERSION = YES; 224 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 225 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 226 | CLANG_WARN_EMPTY_BODY = YES; 227 | CLANG_WARN_ENUM_CONVERSION = YES; 228 | CLANG_WARN_INFINITE_RECURSION = YES; 229 | CLANG_WARN_INT_CONVERSION = YES; 230 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 231 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 232 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 233 | CLANG_WARN_UNREACHABLE_CODE = YES; 234 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 235 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 236 | COPY_PHASE_STRIP = NO; 237 | DEBUG_INFORMATION_FORMAT = dwarf; 238 | ENABLE_STRICT_OBJC_MSGSEND = YES; 239 | ENABLE_TESTABILITY = YES; 240 | GCC_C_LANGUAGE_STANDARD = gnu99; 241 | GCC_DYNAMIC_NO_PIC = NO; 242 | GCC_NO_COMMON_BLOCKS = YES; 243 | GCC_OPTIMIZATION_LEVEL = 0; 244 | GCC_PREPROCESSOR_DEFINITIONS = ( 245 | "DEBUG=1", 246 | "$(inherited)", 247 | ); 248 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 249 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 250 | GCC_WARN_UNDECLARED_SELECTOR = YES; 251 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 252 | GCC_WARN_UNUSED_FUNCTION = YES; 253 | GCC_WARN_UNUSED_VARIABLE = YES; 254 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 255 | MTL_ENABLE_DEBUG_INFO = YES; 256 | ONLY_ACTIVE_ARCH = YES; 257 | SDKROOT = iphoneos; 258 | }; 259 | name = Debug; 260 | }; 261 | 7092D4CD1DED69ED00E9A998 /* Release */ = { 262 | isa = XCBuildConfiguration; 263 | buildSettings = { 264 | ALWAYS_SEARCH_USER_PATHS = NO; 265 | CLANG_ANALYZER_NONNULL = YES; 266 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 267 | CLANG_CXX_LIBRARY = "libc++"; 268 | CLANG_ENABLE_MODULES = YES; 269 | CLANG_ENABLE_OBJC_ARC = YES; 270 | CLANG_WARN_BOOL_CONVERSION = YES; 271 | CLANG_WARN_CONSTANT_CONVERSION = YES; 272 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 273 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 274 | CLANG_WARN_EMPTY_BODY = YES; 275 | CLANG_WARN_ENUM_CONVERSION = YES; 276 | CLANG_WARN_INFINITE_RECURSION = YES; 277 | CLANG_WARN_INT_CONVERSION = YES; 278 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 279 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 280 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 281 | CLANG_WARN_UNREACHABLE_CODE = YES; 282 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 283 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 284 | COPY_PHASE_STRIP = NO; 285 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 286 | ENABLE_NS_ASSERTIONS = NO; 287 | ENABLE_STRICT_OBJC_MSGSEND = YES; 288 | GCC_C_LANGUAGE_STANDARD = gnu99; 289 | GCC_NO_COMMON_BLOCKS = YES; 290 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 291 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 292 | GCC_WARN_UNDECLARED_SELECTOR = YES; 293 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 294 | GCC_WARN_UNUSED_FUNCTION = YES; 295 | GCC_WARN_UNUSED_VARIABLE = YES; 296 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 297 | MTL_ENABLE_DEBUG_INFO = NO; 298 | SDKROOT = iphoneos; 299 | VALIDATE_PRODUCT = YES; 300 | }; 301 | name = Release; 302 | }; 303 | 7092D4CF1DED69ED00E9A998 /* Debug */ = { 304 | isa = XCBuildConfiguration; 305 | buildSettings = { 306 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 307 | DEVELOPMENT_TEAM = Z25J3BA353; 308 | INFOPLIST_FILE = STQRCodeControllerDemo/Info.plist; 309 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 310 | PRODUCT_BUNDLE_IDENTIFIER = com.st.cn.st1; 311 | PRODUCT_NAME = "$(TARGET_NAME)"; 312 | }; 313 | name = Debug; 314 | }; 315 | 7092D4D01DED69ED00E9A998 /* Release */ = { 316 | isa = XCBuildConfiguration; 317 | buildSettings = { 318 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 319 | DEVELOPMENT_TEAM = Z25J3BA353; 320 | INFOPLIST_FILE = STQRCodeControllerDemo/Info.plist; 321 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 322 | PRODUCT_BUNDLE_IDENTIFIER = com.st.cn.st1; 323 | PRODUCT_NAME = "$(TARGET_NAME)"; 324 | }; 325 | name = Release; 326 | }; 327 | /* End XCBuildConfiguration section */ 328 | 329 | /* Begin XCConfigurationList section */ 330 | 7092D4B21DED69ED00E9A998 /* Build configuration list for PBXProject "STQRCodeControllerDemo" */ = { 331 | isa = XCConfigurationList; 332 | buildConfigurations = ( 333 | 7092D4CC1DED69ED00E9A998 /* Debug */, 334 | 7092D4CD1DED69ED00E9A998 /* Release */, 335 | ); 336 | defaultConfigurationIsVisible = 0; 337 | defaultConfigurationName = Release; 338 | }; 339 | 7092D4CE1DED69ED00E9A998 /* Build configuration list for PBXNativeTarget "STQRCodeControllerDemo" */ = { 340 | isa = XCConfigurationList; 341 | buildConfigurations = ( 342 | 7092D4CF1DED69ED00E9A998 /* Debug */, 343 | 7092D4D01DED69ED00E9A998 /* Release */, 344 | ); 345 | defaultConfigurationIsVisible = 0; 346 | defaultConfigurationName = Release; 347 | }; 348 | /* End XCConfigurationList section */ 349 | }; 350 | rootObject = 7092D4AF1DED69ED00E9A998 /* Project object */; 351 | } 352 | -------------------------------------------------------------------------------- /STQRCodeControllerDemo/STQRCodeControllerDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /STQRCodeControllerDemo/STQRCodeControllerDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // STQRCodeControllerDemo 4 | // 5 | // Created by ST on 16/11/29. 6 | // Copyright © 2016年 ST. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /STQRCodeControllerDemo/STQRCodeControllerDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // STQRCodeControllerDemo 4 | // 5 | // Created by ST on 16/11/29. 6 | // Copyright © 2016年 ST. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "TestController.h" 11 | 12 | @interface AppDelegate () 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 18 | 19 | self.window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds]; 20 | UINavigationController *navVC = [[UINavigationController alloc]initWithRootViewController:[[TestController alloc]init]]; 21 | self.window.rootViewController = navVC; 22 | [self.window makeKeyAndVisible]; 23 | return YES; 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /STQRCodeControllerDemo/STQRCodeControllerDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | } 43 | ], 44 | "info" : { 45 | "version" : 1, 46 | "author" : "xcode" 47 | } 48 | } -------------------------------------------------------------------------------- /STQRCodeControllerDemo/STQRCodeControllerDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /STQRCodeControllerDemo/STQRCodeControllerDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | NSCameraUsageDescription 24 | 开启相机 25 | NSPhotoLibraryUsageDescription 26 | 开启相册 27 | 28 | NSMicrophoneUsageDescription 29 | App需要您的同意,才能访问麦克风 30 | 31 | NSAppleMusicUsageDescription 32 | App需要您的同意,才能访问媒体资料库 33 | 34 | UILaunchStoryboardName 35 | LaunchScreen 36 | UIMainStoryboardFile 37 | 38 | UIRequiredDeviceCapabilities 39 | 40 | armv7 41 | 42 | UISupportedInterfaceOrientations 43 | 44 | UIInterfaceOrientationPortrait 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /STQRCodeControllerDemo/STQRCodeControllerDemo/TestController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TestController.h 3 | // STQRCodeController 4 | // 5 | // Created by ST on 16/11/28. 6 | // Copyright © 2016年 ST. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TestController : UIViewController 12 | @end 13 | -------------------------------------------------------------------------------- /STQRCodeControllerDemo/STQRCodeControllerDemo/TestController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TestController.m 3 | // STQRCodeController 4 | // 5 | // Created by ST on 16/11/28. 6 | // Copyright © 2016年 ST. All rights reserved. 7 | // 8 | 9 | #import "TestController.h" 10 | #import "STQRCodeController.h" 11 | #import "STQRCodeAlert.h" 12 | @interface TestController () 13 | /** 1. */ 14 | @property(nonatomic, strong)UIButton *buttonGoQR; 15 | @end 16 | 17 | @implementation TestController 18 | 19 | #pragma mark - --- 1.init 生命周期 --- 20 | 21 | - (void)viewDidLoad 22 | { 23 | [super viewDidLoad]; 24 | 25 | self.view.backgroundColor = [UIColor whiteColor]; 26 | [self.view addSubview:self.buttonGoQR]; 27 | } 28 | 29 | #pragma mark - --- 2.delegate 视图委托 --- 30 | - (void)qrcodeController:(STQRCodeController *)qrcodeController readerScanResult:(NSString *)readerScanResult type:(STQRCodeResultType)resultType 31 | { 32 | NSLog(@"%s %@", __FUNCTION__, readerScanResult); 33 | NSLog(@"%s %lu", __FUNCTION__, (unsigned long)resultType); 34 | 35 | if ((resultType == STQRCodeResultTypeError) || (resultType == STQRCodeResultTypeNoInfo)) { 36 | readerScanResult = @"没有扫描到结果"; 37 | } 38 | 39 | [STQRCodeAlert showWithTitle:readerScanResult]; 40 | } 41 | #pragma mark - --- 3.event response 事件相应 --- 42 | 43 | #pragma mark - --- 4.private methods 私有方法 --- 44 | - (void)gotoQR { 45 | STQRCodeController *codeVC = [[STQRCodeController alloc]init]; 46 | codeVC.delegate = self; 47 | UINavigationController *navVC = [[UINavigationController alloc]initWithRootViewController:codeVC]; 48 | [self presentViewController:navVC animated:YES completion:nil]; 49 | } 50 | #pragma mark - --- 5.setters 属性 --- 51 | 52 | #pragma mark - --- 6.getters 属性 —-- 53 | - (UIButton *)buttonGoQR 54 | { 55 | if (!_buttonGoQR) { 56 | _buttonGoQR = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 200, 44)]; 57 | [_buttonGoQR setTitle:@"跳转到二维码界面" forState:UIControlStateNormal]; 58 | [_buttonGoQR setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 59 | [_buttonGoQR setBackgroundColor:[UIColor magentaColor]]; 60 | _buttonGoQR.center = CGPointMake(self.view.bounds.size.width/2, self.view.bounds.size.height/2); 61 | [_buttonGoQR addTarget:self action:@selector(gotoQR) forControlEvents:UIControlEventTouchUpInside]; 62 | } 63 | return _buttonGoQR; 64 | } 65 | @end 66 | -------------------------------------------------------------------------------- /STQRCodeControllerDemo/STQRCodeControllerDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // STQRCodeControllerDemo 4 | // 5 | // Created by ST on 16/11/29. 6 | // Copyright © 2016年 ST. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | --------------------------------------------------------------------------------