├── .gitignore ├── CONTRIBUTORS.md ├── Example ├── QRCodeReaderViewControllerExample.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── QRCodeReaderViewControllerExample │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Base.lproj │ │ └── Main.storyboard │ ├── Info.plist │ ├── Launch Screen.storyboard │ ├── ViewController.h │ ├── ViewController.m │ └── main.m └── QRCodeReaderViewControllerExampleTests │ ├── Info.plist │ └── QRCodeReaderViewControllerExampleTests.m ├── LICENSE ├── MQRCodeReaderViewController.podspec ├── QRCodeReaderViewController.podspec ├── QRCodeReaderViewController ├── QRCameraSwitchButton.h ├── QRCameraSwitchButton.m ├── QRCodeReader.h ├── QRCodeReader.m ├── QRCodeReaderDelegate.h ├── QRCodeReaderView │ ├── QRCodeReaderAanimationLineView.h │ ├── QRCodeReaderAanimationLineView.m │ ├── QRCodeReaderMaskView.h │ ├── QRCodeReaderMaskView.m │ ├── QRCodeReaderView.h │ └── QRCodeReaderView.m ├── QRCodeReaderViewController.h ├── QRCodeReaderViewController.m └── Resources │ ├── QRCodeBottomLeft@2x.png │ ├── QRCodeBottomLeft@3x.png │ ├── QRCodeBottomRight@2x.png │ ├── QRCodeBottomRight@3x.png │ ├── QRCodeLine@2x.png │ ├── QRCodeLine@3x.png │ ├── QRCodeTopLeft@2x.png │ ├── QRCodeTopLeft@3x.png │ ├── QRCodeTopRight@2x.png │ └── QRCodeTopRight@3x.png ├── README.md └── web ├── qrcodereaderviewcontroller_header.png └── screenshot.jpg /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | */build/* 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | profile 14 | *.moved-aside 15 | DerivedData 16 | .idea/ 17 | *.hmap 18 | *.xccheckout 19 | -------------------------------------------------------------------------------- /CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | ## Contributors 2 | This is the official list of people who can contribute (and typically have contributed) code to the QRCodeReaderViewController repository. 3 | 4 | Names should be added to this file like so: 5 | ``` * [Firstname Lastname|Nickname](github_page_url)``` 6 | 7 | Please keep the list sorted. 8 | 9 | ### Lead developer 10 | 11 | * [Yannick Loriot](https://github.com/YannickL) 12 | 13 | ### People and companies, who have contributed 14 | 15 | * [Akira Matsuda](https://github.com/0x0c) 16 | * [Andrea Mazzini](https://github.com/andreamazz) 17 | * [Jan](https://github.com/jaltek) -------------------------------------------------------------------------------- /Example/QRCodeReaderViewControllerExample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | C154819C1BBA87DA00124400 /* QRCodeBottomLeft@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C15481921BBA87DA00124400 /* QRCodeBottomLeft@2x.png */; settings = {ASSET_TAGS = (); }; }; 11 | C154819D1BBA87DA00124400 /* QRCodeBottomLeft@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = C15481931BBA87DA00124400 /* QRCodeBottomLeft@3x.png */; settings = {ASSET_TAGS = (); }; }; 12 | C154819E1BBA87DA00124400 /* QRCodeBottomRight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C15481941BBA87DA00124400 /* QRCodeBottomRight@2x.png */; settings = {ASSET_TAGS = (); }; }; 13 | C154819F1BBA87DA00124400 /* QRCodeBottomRight@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = C15481951BBA87DA00124400 /* QRCodeBottomRight@3x.png */; settings = {ASSET_TAGS = (); }; }; 14 | C15481A01BBA87DA00124400 /* QRCodeLine@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C15481961BBA87DA00124400 /* QRCodeLine@2x.png */; settings = {ASSET_TAGS = (); }; }; 15 | C15481A11BBA87DA00124400 /* QRCodeLine@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = C15481971BBA87DA00124400 /* QRCodeLine@3x.png */; settings = {ASSET_TAGS = (); }; }; 16 | C15481A21BBA87DA00124400 /* QRCodeTopLeft@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C15481981BBA87DA00124400 /* QRCodeTopLeft@2x.png */; settings = {ASSET_TAGS = (); }; }; 17 | C15481A31BBA87DA00124400 /* QRCodeTopLeft@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = C15481991BBA87DA00124400 /* QRCodeTopLeft@3x.png */; settings = {ASSET_TAGS = (); }; }; 18 | C15481A41BBA87DA00124400 /* QRCodeTopRight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C154819A1BBA87DA00124400 /* QRCodeTopRight@2x.png */; settings = {ASSET_TAGS = (); }; }; 19 | C15481A51BBA87DA00124400 /* QRCodeTopRight@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = C154819B1BBA87DA00124400 /* QRCodeTopRight@3x.png */; settings = {ASSET_TAGS = (); }; }; 20 | C18C20671BB3CCE3007FECF1 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C18C20661BB3CCE3007FECF1 /* Launch Screen.storyboard */; settings = {ASSET_TAGS = (); }; }; 21 | C18C206C1BB3DF21007FECF1 /* QRCodeReaderMaskView.m in Sources */ = {isa = PBXBuildFile; fileRef = C18C206B1BB3DF21007FECF1 /* QRCodeReaderMaskView.m */; settings = {ASSET_TAGS = (); }; }; 22 | C18C206F1BB3DF43007FECF1 /* QRCodeReaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = C18C206E1BB3DF43007FECF1 /* QRCodeReaderView.m */; settings = {ASSET_TAGS = (); }; }; 23 | C18C20721BB3E458007FECF1 /* QRCodeReaderAanimationLineView.m in Sources */ = {isa = PBXBuildFile; fileRef = C18C20711BB3E458007FECF1 /* QRCodeReaderAanimationLineView.m */; settings = {ASSET_TAGS = (); }; }; 24 | CE29601E1987F124008FA93B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = CE29601D1987F124008FA93B /* main.m */; }; 25 | CE2960211987F124008FA93B /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CE2960201987F124008FA93B /* AppDelegate.m */; }; 26 | CE2960241987F124008FA93B /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CE2960231987F124008FA93B /* ViewController.m */; }; 27 | CE2960271987F124008FA93B /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CE2960251987F124008FA93B /* Main.storyboard */; }; 28 | CE2960351987F125008FA93B /* QRCodeReaderViewControllerExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CE2960341987F125008FA93B /* QRCodeReaderViewControllerExampleTests.m */; }; 29 | CE2960421987F140008FA93B /* QRCodeReaderViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CE2960411987F140008FA93B /* QRCodeReaderViewController.m */; }; 30 | CE2960431987F140008FA93B /* QRCodeReaderViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CE2960411987F140008FA93B /* QRCodeReaderViewController.m */; }; 31 | CE99CEFD1A9BCA1100CB8AD8 /* QRCodeReader.m in Sources */ = {isa = PBXBuildFile; fileRef = CE99CEFC1A9BCA1100CB8AD8 /* QRCodeReader.m */; }; 32 | CEAF7A691A16B05400991CF8 /* QRCameraSwitchButton.m in Sources */ = {isa = PBXBuildFile; fileRef = CEAF7A681A16B05400991CF8 /* QRCameraSwitchButton.m */; }; 33 | /* End PBXBuildFile section */ 34 | 35 | /* Begin PBXContainerItemProxy section */ 36 | CE29602F1987F125008FA93B /* PBXContainerItemProxy */ = { 37 | isa = PBXContainerItemProxy; 38 | containerPortal = CE2960101987F124008FA93B /* Project object */; 39 | proxyType = 1; 40 | remoteGlobalIDString = CE2960171987F124008FA93B; 41 | remoteInfo = QRCodeReaderViewControllerExample; 42 | }; 43 | /* End PBXContainerItemProxy section */ 44 | 45 | /* Begin PBXFileReference section */ 46 | C15481921BBA87DA00124400 /* QRCodeBottomLeft@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "QRCodeBottomLeft@2x.png"; sourceTree = ""; }; 47 | C15481931BBA87DA00124400 /* QRCodeBottomLeft@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "QRCodeBottomLeft@3x.png"; sourceTree = ""; }; 48 | C15481941BBA87DA00124400 /* QRCodeBottomRight@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "QRCodeBottomRight@2x.png"; sourceTree = ""; }; 49 | C15481951BBA87DA00124400 /* QRCodeBottomRight@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "QRCodeBottomRight@3x.png"; sourceTree = ""; }; 50 | C15481961BBA87DA00124400 /* QRCodeLine@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "QRCodeLine@2x.png"; sourceTree = ""; }; 51 | C15481971BBA87DA00124400 /* QRCodeLine@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "QRCodeLine@3x.png"; sourceTree = ""; }; 52 | C15481981BBA87DA00124400 /* QRCodeTopLeft@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "QRCodeTopLeft@2x.png"; sourceTree = ""; }; 53 | C15481991BBA87DA00124400 /* QRCodeTopLeft@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "QRCodeTopLeft@3x.png"; sourceTree = ""; }; 54 | C154819A1BBA87DA00124400 /* QRCodeTopRight@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "QRCodeTopRight@2x.png"; sourceTree = ""; }; 55 | C154819B1BBA87DA00124400 /* QRCodeTopRight@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "QRCodeTopRight@3x.png"; sourceTree = ""; }; 56 | C18C20661BB3CCE3007FECF1 /* Launch Screen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = ""; }; 57 | C18C206A1BB3DF21007FECF1 /* QRCodeReaderMaskView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QRCodeReaderMaskView.h; sourceTree = ""; }; 58 | C18C206B1BB3DF21007FECF1 /* QRCodeReaderMaskView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QRCodeReaderMaskView.m; sourceTree = ""; }; 59 | C18C206D1BB3DF43007FECF1 /* QRCodeReaderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QRCodeReaderView.h; sourceTree = ""; }; 60 | C18C206E1BB3DF43007FECF1 /* QRCodeReaderView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QRCodeReaderView.m; sourceTree = ""; }; 61 | C18C20701BB3E458007FECF1 /* QRCodeReaderAanimationLineView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QRCodeReaderAanimationLineView.h; sourceTree = ""; }; 62 | C18C20711BB3E458007FECF1 /* QRCodeReaderAanimationLineView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QRCodeReaderAanimationLineView.m; sourceTree = ""; }; 63 | CE2960181987F124008FA93B /* QRCodeReaderViewControllerExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = QRCodeReaderViewControllerExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 64 | CE29601C1987F124008FA93B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 65 | CE29601D1987F124008FA93B /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 66 | CE29601F1987F124008FA93B /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 67 | CE2960201987F124008FA93B /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 68 | CE2960221987F124008FA93B /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 69 | CE2960231987F124008FA93B /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 70 | CE2960261987F124008FA93B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 71 | CE29602E1987F125008FA93B /* QRCodeReaderViewControllerExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = QRCodeReaderViewControllerExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 72 | CE2960331987F125008FA93B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 73 | CE2960341987F125008FA93B /* QRCodeReaderViewControllerExampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = QRCodeReaderViewControllerExampleTests.m; sourceTree = ""; }; 74 | CE29603F1987F140008FA93B /* QRCodeReaderDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QRCodeReaderDelegate.h; sourceTree = ""; }; 75 | CE2960401987F140008FA93B /* QRCodeReaderViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QRCodeReaderViewController.h; sourceTree = ""; }; 76 | CE2960411987F140008FA93B /* QRCodeReaderViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QRCodeReaderViewController.m; sourceTree = ""; }; 77 | CE99CEFB1A9BCA1100CB8AD8 /* QRCodeReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QRCodeReader.h; sourceTree = ""; }; 78 | CE99CEFC1A9BCA1100CB8AD8 /* QRCodeReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QRCodeReader.m; sourceTree = ""; }; 79 | CEAF7A671A16B05400991CF8 /* QRCameraSwitchButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QRCameraSwitchButton.h; sourceTree = ""; }; 80 | CEAF7A681A16B05400991CF8 /* QRCameraSwitchButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QRCameraSwitchButton.m; sourceTree = ""; }; 81 | /* End PBXFileReference section */ 82 | 83 | /* Begin PBXFrameworksBuildPhase section */ 84 | CE2960151987F124008FA93B /* Frameworks */ = { 85 | isa = PBXFrameworksBuildPhase; 86 | buildActionMask = 2147483647; 87 | files = ( 88 | ); 89 | runOnlyForDeploymentPostprocessing = 0; 90 | }; 91 | CE29602B1987F124008FA93B /* Frameworks */ = { 92 | isa = PBXFrameworksBuildPhase; 93 | buildActionMask = 2147483647; 94 | files = ( 95 | ); 96 | runOnlyForDeploymentPostprocessing = 0; 97 | }; 98 | /* End PBXFrameworksBuildPhase section */ 99 | 100 | /* Begin PBXGroup section */ 101 | C15481911BBA87DA00124400 /* Resources */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | C15481921BBA87DA00124400 /* QRCodeBottomLeft@2x.png */, 105 | C15481931BBA87DA00124400 /* QRCodeBottomLeft@3x.png */, 106 | C15481941BBA87DA00124400 /* QRCodeBottomRight@2x.png */, 107 | C15481951BBA87DA00124400 /* QRCodeBottomRight@3x.png */, 108 | C15481961BBA87DA00124400 /* QRCodeLine@2x.png */, 109 | C15481971BBA87DA00124400 /* QRCodeLine@3x.png */, 110 | C15481981BBA87DA00124400 /* QRCodeTopLeft@2x.png */, 111 | C15481991BBA87DA00124400 /* QRCodeTopLeft@3x.png */, 112 | C154819A1BBA87DA00124400 /* QRCodeTopRight@2x.png */, 113 | C154819B1BBA87DA00124400 /* QRCodeTopRight@3x.png */, 114 | ); 115 | path = Resources; 116 | sourceTree = ""; 117 | }; 118 | C18C20691BB3DF11007FECF1 /* QRCodeReaderView */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | C18C206D1BB3DF43007FECF1 /* QRCodeReaderView.h */, 122 | C18C206E1BB3DF43007FECF1 /* QRCodeReaderView.m */, 123 | C18C206A1BB3DF21007FECF1 /* QRCodeReaderMaskView.h */, 124 | C18C206B1BB3DF21007FECF1 /* QRCodeReaderMaskView.m */, 125 | C18C20701BB3E458007FECF1 /* QRCodeReaderAanimationLineView.h */, 126 | C18C20711BB3E458007FECF1 /* QRCodeReaderAanimationLineView.m */, 127 | ); 128 | path = QRCodeReaderView; 129 | sourceTree = ""; 130 | }; 131 | CE29600F1987F124008FA93B = { 132 | isa = PBXGroup; 133 | children = ( 134 | CE29603E1987F140008FA93B /* QRCodeReaderViewController */, 135 | CE29601A1987F124008FA93B /* QRCodeReaderViewControllerExample */, 136 | CE2960311987F125008FA93B /* QRCodeReaderViewControllerExampleTests */, 137 | CE2960191987F124008FA93B /* Products */, 138 | ); 139 | sourceTree = ""; 140 | }; 141 | CE2960191987F124008FA93B /* Products */ = { 142 | isa = PBXGroup; 143 | children = ( 144 | CE2960181987F124008FA93B /* QRCodeReaderViewControllerExample.app */, 145 | CE29602E1987F125008FA93B /* QRCodeReaderViewControllerExampleTests.xctest */, 146 | ); 147 | name = Products; 148 | sourceTree = ""; 149 | }; 150 | CE29601A1987F124008FA93B /* QRCodeReaderViewControllerExample */ = { 151 | isa = PBXGroup; 152 | children = ( 153 | CE29601F1987F124008FA93B /* AppDelegate.h */, 154 | CE2960201987F124008FA93B /* AppDelegate.m */, 155 | CE2960221987F124008FA93B /* ViewController.h */, 156 | CE2960231987F124008FA93B /* ViewController.m */, 157 | CE2960251987F124008FA93B /* Main.storyboard */, 158 | CE29601B1987F124008FA93B /* Supporting Files */, 159 | ); 160 | path = QRCodeReaderViewControllerExample; 161 | sourceTree = ""; 162 | }; 163 | CE29601B1987F124008FA93B /* Supporting Files */ = { 164 | isa = PBXGroup; 165 | children = ( 166 | CE29601C1987F124008FA93B /* Info.plist */, 167 | CE29601D1987F124008FA93B /* main.m */, 168 | C18C20661BB3CCE3007FECF1 /* Launch Screen.storyboard */, 169 | ); 170 | name = "Supporting Files"; 171 | sourceTree = ""; 172 | }; 173 | CE2960311987F125008FA93B /* QRCodeReaderViewControllerExampleTests */ = { 174 | isa = PBXGroup; 175 | children = ( 176 | CE2960341987F125008FA93B /* QRCodeReaderViewControllerExampleTests.m */, 177 | CE2960321987F125008FA93B /* Supporting Files */, 178 | ); 179 | path = QRCodeReaderViewControllerExampleTests; 180 | sourceTree = ""; 181 | }; 182 | CE2960321987F125008FA93B /* Supporting Files */ = { 183 | isa = PBXGroup; 184 | children = ( 185 | CE2960331987F125008FA93B /* Info.plist */, 186 | ); 187 | name = "Supporting Files"; 188 | sourceTree = ""; 189 | }; 190 | CE29603E1987F140008FA93B /* QRCodeReaderViewController */ = { 191 | isa = PBXGroup; 192 | children = ( 193 | C15481911BBA87DA00124400 /* Resources */, 194 | C18C20691BB3DF11007FECF1 /* QRCodeReaderView */, 195 | CE29603F1987F140008FA93B /* QRCodeReaderDelegate.h */, 196 | CE2960401987F140008FA93B /* QRCodeReaderViewController.h */, 197 | CE2960411987F140008FA93B /* QRCodeReaderViewController.m */, 198 | CE99CEFB1A9BCA1100CB8AD8 /* QRCodeReader.h */, 199 | CE99CEFC1A9BCA1100CB8AD8 /* QRCodeReader.m */, 200 | CEAF7A671A16B05400991CF8 /* QRCameraSwitchButton.h */, 201 | CEAF7A681A16B05400991CF8 /* QRCameraSwitchButton.m */, 202 | ); 203 | name = QRCodeReaderViewController; 204 | path = ../QRCodeReaderViewController; 205 | sourceTree = ""; 206 | }; 207 | /* End PBXGroup section */ 208 | 209 | /* Begin PBXNativeTarget section */ 210 | CE2960171987F124008FA93B /* QRCodeReaderViewControllerExample */ = { 211 | isa = PBXNativeTarget; 212 | buildConfigurationList = CE2960381987F125008FA93B /* Build configuration list for PBXNativeTarget "QRCodeReaderViewControllerExample" */; 213 | buildPhases = ( 214 | CE2960141987F124008FA93B /* Sources */, 215 | CE2960151987F124008FA93B /* Frameworks */, 216 | CE2960161987F124008FA93B /* Resources */, 217 | ); 218 | buildRules = ( 219 | ); 220 | dependencies = ( 221 | ); 222 | name = QRCodeReaderViewControllerExample; 223 | productName = QRCodeReaderViewControllerExample; 224 | productReference = CE2960181987F124008FA93B /* QRCodeReaderViewControllerExample.app */; 225 | productType = "com.apple.product-type.application"; 226 | }; 227 | CE29602D1987F124008FA93B /* QRCodeReaderViewControllerExampleTests */ = { 228 | isa = PBXNativeTarget; 229 | buildConfigurationList = CE29603B1987F125008FA93B /* Build configuration list for PBXNativeTarget "QRCodeReaderViewControllerExampleTests" */; 230 | buildPhases = ( 231 | CE29602A1987F124008FA93B /* Sources */, 232 | CE29602B1987F124008FA93B /* Frameworks */, 233 | CE29602C1987F124008FA93B /* Resources */, 234 | ); 235 | buildRules = ( 236 | ); 237 | dependencies = ( 238 | CE2960301987F125008FA93B /* PBXTargetDependency */, 239 | ); 240 | name = QRCodeReaderViewControllerExampleTests; 241 | productName = QRCodeReaderViewControllerExampleTests; 242 | productReference = CE29602E1987F125008FA93B /* QRCodeReaderViewControllerExampleTests.xctest */; 243 | productType = "com.apple.product-type.bundle.unit-test"; 244 | }; 245 | /* End PBXNativeTarget section */ 246 | 247 | /* Begin PBXProject section */ 248 | CE2960101987F124008FA93B /* Project object */ = { 249 | isa = PBXProject; 250 | attributes = { 251 | LastUpgradeCheck = 0600; 252 | ORGANIZATIONNAME = "Yannick Loriot"; 253 | TargetAttributes = { 254 | CE2960171987F124008FA93B = { 255 | CreatedOnToolsVersion = 6.0; 256 | DevelopmentTeam = ZQA8RKS39U; 257 | }; 258 | CE29602D1987F124008FA93B = { 259 | CreatedOnToolsVersion = 6.0; 260 | TestTargetID = CE2960171987F124008FA93B; 261 | }; 262 | }; 263 | }; 264 | buildConfigurationList = CE2960131987F124008FA93B /* Build configuration list for PBXProject "QRCodeReaderViewControllerExample" */; 265 | compatibilityVersion = "Xcode 3.2"; 266 | developmentRegion = English; 267 | hasScannedForEncodings = 0; 268 | knownRegions = ( 269 | en, 270 | Base, 271 | ); 272 | mainGroup = CE29600F1987F124008FA93B; 273 | productRefGroup = CE2960191987F124008FA93B /* Products */; 274 | projectDirPath = ""; 275 | projectRoot = ""; 276 | targets = ( 277 | CE2960171987F124008FA93B /* QRCodeReaderViewControllerExample */, 278 | CE29602D1987F124008FA93B /* QRCodeReaderViewControllerExampleTests */, 279 | ); 280 | }; 281 | /* End PBXProject section */ 282 | 283 | /* Begin PBXResourcesBuildPhase section */ 284 | CE2960161987F124008FA93B /* Resources */ = { 285 | isa = PBXResourcesBuildPhase; 286 | buildActionMask = 2147483647; 287 | files = ( 288 | C154819E1BBA87DA00124400 /* QRCodeBottomRight@2x.png in Resources */, 289 | C154819D1BBA87DA00124400 /* QRCodeBottomLeft@3x.png in Resources */, 290 | C18C20671BB3CCE3007FECF1 /* Launch Screen.storyboard in Resources */, 291 | C15481A21BBA87DA00124400 /* QRCodeTopLeft@2x.png in Resources */, 292 | C15481A11BBA87DA00124400 /* QRCodeLine@3x.png in Resources */, 293 | C154819F1BBA87DA00124400 /* QRCodeBottomRight@3x.png in Resources */, 294 | CE2960271987F124008FA93B /* Main.storyboard in Resources */, 295 | C15481A31BBA87DA00124400 /* QRCodeTopLeft@3x.png in Resources */, 296 | C15481A41BBA87DA00124400 /* QRCodeTopRight@2x.png in Resources */, 297 | C15481A51BBA87DA00124400 /* QRCodeTopRight@3x.png in Resources */, 298 | C15481A01BBA87DA00124400 /* QRCodeLine@2x.png in Resources */, 299 | C154819C1BBA87DA00124400 /* QRCodeBottomLeft@2x.png in Resources */, 300 | ); 301 | runOnlyForDeploymentPostprocessing = 0; 302 | }; 303 | CE29602C1987F124008FA93B /* Resources */ = { 304 | isa = PBXResourcesBuildPhase; 305 | buildActionMask = 2147483647; 306 | files = ( 307 | ); 308 | runOnlyForDeploymentPostprocessing = 0; 309 | }; 310 | /* End PBXResourcesBuildPhase section */ 311 | 312 | /* Begin PBXSourcesBuildPhase section */ 313 | CE2960141987F124008FA93B /* Sources */ = { 314 | isa = PBXSourcesBuildPhase; 315 | buildActionMask = 2147483647; 316 | files = ( 317 | C18C206F1BB3DF43007FECF1 /* QRCodeReaderView.m in Sources */, 318 | CE2960241987F124008FA93B /* ViewController.m in Sources */, 319 | C18C206C1BB3DF21007FECF1 /* QRCodeReaderMaskView.m in Sources */, 320 | C18C20721BB3E458007FECF1 /* QRCodeReaderAanimationLineView.m in Sources */, 321 | CEAF7A691A16B05400991CF8 /* QRCameraSwitchButton.m in Sources */, 322 | CE99CEFD1A9BCA1100CB8AD8 /* QRCodeReader.m in Sources */, 323 | CE2960211987F124008FA93B /* AppDelegate.m in Sources */, 324 | CE29601E1987F124008FA93B /* main.m in Sources */, 325 | CE2960421987F140008FA93B /* QRCodeReaderViewController.m in Sources */, 326 | ); 327 | runOnlyForDeploymentPostprocessing = 0; 328 | }; 329 | CE29602A1987F124008FA93B /* Sources */ = { 330 | isa = PBXSourcesBuildPhase; 331 | buildActionMask = 2147483647; 332 | files = ( 333 | CE2960351987F125008FA93B /* QRCodeReaderViewControllerExampleTests.m in Sources */, 334 | CE2960431987F140008FA93B /* QRCodeReaderViewController.m in Sources */, 335 | ); 336 | runOnlyForDeploymentPostprocessing = 0; 337 | }; 338 | /* End PBXSourcesBuildPhase section */ 339 | 340 | /* Begin PBXTargetDependency section */ 341 | CE2960301987F125008FA93B /* PBXTargetDependency */ = { 342 | isa = PBXTargetDependency; 343 | target = CE2960171987F124008FA93B /* QRCodeReaderViewControllerExample */; 344 | targetProxy = CE29602F1987F125008FA93B /* PBXContainerItemProxy */; 345 | }; 346 | /* End PBXTargetDependency section */ 347 | 348 | /* Begin PBXVariantGroup section */ 349 | CE2960251987F124008FA93B /* Main.storyboard */ = { 350 | isa = PBXVariantGroup; 351 | children = ( 352 | CE2960261987F124008FA93B /* Base */, 353 | ); 354 | name = Main.storyboard; 355 | sourceTree = ""; 356 | }; 357 | /* End PBXVariantGroup section */ 358 | 359 | /* Begin XCBuildConfiguration section */ 360 | CE2960361987F125008FA93B /* Debug */ = { 361 | isa = XCBuildConfiguration; 362 | buildSettings = { 363 | ALWAYS_SEARCH_USER_PATHS = NO; 364 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 365 | CLANG_CXX_LIBRARY = "libc++"; 366 | CLANG_ENABLE_MODULES = YES; 367 | CLANG_ENABLE_OBJC_ARC = YES; 368 | CLANG_WARN_BOOL_CONVERSION = YES; 369 | CLANG_WARN_CONSTANT_CONVERSION = YES; 370 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 371 | CLANG_WARN_EMPTY_BODY = YES; 372 | CLANG_WARN_ENUM_CONVERSION = YES; 373 | CLANG_WARN_INT_CONVERSION = YES; 374 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 375 | CLANG_WARN_UNREACHABLE_CODE = YES; 376 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 377 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 378 | COPY_PHASE_STRIP = NO; 379 | ENABLE_STRICT_OBJC_MSGSEND = YES; 380 | GCC_C_LANGUAGE_STANDARD = gnu99; 381 | GCC_DYNAMIC_NO_PIC = NO; 382 | GCC_OPTIMIZATION_LEVEL = 0; 383 | GCC_PREPROCESSOR_DEFINITIONS = ( 384 | "DEBUG=1", 385 | "$(inherited)", 386 | ); 387 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 388 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 389 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 390 | GCC_WARN_UNDECLARED_SELECTOR = YES; 391 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 392 | GCC_WARN_UNUSED_FUNCTION = YES; 393 | GCC_WARN_UNUSED_VARIABLE = YES; 394 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 395 | MTL_ENABLE_DEBUG_INFO = YES; 396 | ONLY_ACTIVE_ARCH = YES; 397 | SDKROOT = iphoneos; 398 | TARGETED_DEVICE_FAMILY = "1,2"; 399 | }; 400 | name = Debug; 401 | }; 402 | CE2960371987F125008FA93B /* Release */ = { 403 | isa = XCBuildConfiguration; 404 | buildSettings = { 405 | ALWAYS_SEARCH_USER_PATHS = NO; 406 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 407 | CLANG_CXX_LIBRARY = "libc++"; 408 | CLANG_ENABLE_MODULES = YES; 409 | CLANG_ENABLE_OBJC_ARC = YES; 410 | CLANG_WARN_BOOL_CONVERSION = YES; 411 | CLANG_WARN_CONSTANT_CONVERSION = YES; 412 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 413 | CLANG_WARN_EMPTY_BODY = YES; 414 | CLANG_WARN_ENUM_CONVERSION = YES; 415 | CLANG_WARN_INT_CONVERSION = YES; 416 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 417 | CLANG_WARN_UNREACHABLE_CODE = YES; 418 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 419 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 420 | COPY_PHASE_STRIP = YES; 421 | ENABLE_NS_ASSERTIONS = NO; 422 | ENABLE_STRICT_OBJC_MSGSEND = YES; 423 | GCC_C_LANGUAGE_STANDARD = gnu99; 424 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 425 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 426 | GCC_WARN_UNDECLARED_SELECTOR = YES; 427 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 428 | GCC_WARN_UNUSED_FUNCTION = YES; 429 | GCC_WARN_UNUSED_VARIABLE = YES; 430 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 431 | MTL_ENABLE_DEBUG_INFO = NO; 432 | SDKROOT = iphoneos; 433 | TARGETED_DEVICE_FAMILY = "1,2"; 434 | VALIDATE_PRODUCT = YES; 435 | }; 436 | name = Release; 437 | }; 438 | CE2960391987F125008FA93B /* Debug */ = { 439 | isa = XCBuildConfiguration; 440 | buildSettings = { 441 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 442 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 443 | CODE_SIGN_IDENTITY = "iPhone Developer"; 444 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 445 | INFOPLIST_FILE = QRCodeReaderViewControllerExample/Info.plist; 446 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 447 | PRODUCT_NAME = "$(TARGET_NAME)"; 448 | PROVISIONING_PROFILE = ""; 449 | }; 450 | name = Debug; 451 | }; 452 | CE29603A1987F125008FA93B /* Release */ = { 453 | isa = XCBuildConfiguration; 454 | buildSettings = { 455 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 456 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 457 | CODE_SIGN_IDENTITY = "iPhone Developer"; 458 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 459 | INFOPLIST_FILE = QRCodeReaderViewControllerExample/Info.plist; 460 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 461 | PRODUCT_NAME = "$(TARGET_NAME)"; 462 | PROVISIONING_PROFILE = ""; 463 | }; 464 | name = Release; 465 | }; 466 | CE29603C1987F125008FA93B /* Debug */ = { 467 | isa = XCBuildConfiguration; 468 | buildSettings = { 469 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/QRCodeReaderViewControllerExample.app/QRCodeReaderViewControllerExample"; 470 | FRAMEWORK_SEARCH_PATHS = ( 471 | "$(SDKROOT)/Developer/Library/Frameworks", 472 | "$(inherited)", 473 | ); 474 | GCC_PREPROCESSOR_DEFINITIONS = ( 475 | "DEBUG=1", 476 | "$(inherited)", 477 | ); 478 | INFOPLIST_FILE = QRCodeReaderViewControllerExampleTests/Info.plist; 479 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 480 | PRODUCT_NAME = "$(TARGET_NAME)"; 481 | TEST_HOST = "$(BUNDLE_LOADER)"; 482 | }; 483 | name = Debug; 484 | }; 485 | CE29603D1987F125008FA93B /* Release */ = { 486 | isa = XCBuildConfiguration; 487 | buildSettings = { 488 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/QRCodeReaderViewControllerExample.app/QRCodeReaderViewControllerExample"; 489 | FRAMEWORK_SEARCH_PATHS = ( 490 | "$(SDKROOT)/Developer/Library/Frameworks", 491 | "$(inherited)", 492 | ); 493 | INFOPLIST_FILE = QRCodeReaderViewControllerExampleTests/Info.plist; 494 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 495 | PRODUCT_NAME = "$(TARGET_NAME)"; 496 | TEST_HOST = "$(BUNDLE_LOADER)"; 497 | }; 498 | name = Release; 499 | }; 500 | /* End XCBuildConfiguration section */ 501 | 502 | /* Begin XCConfigurationList section */ 503 | CE2960131987F124008FA93B /* Build configuration list for PBXProject "QRCodeReaderViewControllerExample" */ = { 504 | isa = XCConfigurationList; 505 | buildConfigurations = ( 506 | CE2960361987F125008FA93B /* Debug */, 507 | CE2960371987F125008FA93B /* Release */, 508 | ); 509 | defaultConfigurationIsVisible = 0; 510 | defaultConfigurationName = Release; 511 | }; 512 | CE2960381987F125008FA93B /* Build configuration list for PBXNativeTarget "QRCodeReaderViewControllerExample" */ = { 513 | isa = XCConfigurationList; 514 | buildConfigurations = ( 515 | CE2960391987F125008FA93B /* Debug */, 516 | CE29603A1987F125008FA93B /* Release */, 517 | ); 518 | defaultConfigurationIsVisible = 0; 519 | defaultConfigurationName = Release; 520 | }; 521 | CE29603B1987F125008FA93B /* Build configuration list for PBXNativeTarget "QRCodeReaderViewControllerExampleTests" */ = { 522 | isa = XCConfigurationList; 523 | buildConfigurations = ( 524 | CE29603C1987F125008FA93B /* Debug */, 525 | CE29603D1987F125008FA93B /* Release */, 526 | ); 527 | defaultConfigurationIsVisible = 0; 528 | defaultConfigurationName = Release; 529 | }; 530 | /* End XCConfigurationList section */ 531 | }; 532 | rootObject = CE2960101987F124008FA93B /* Project object */; 533 | } 534 | -------------------------------------------------------------------------------- /Example/QRCodeReaderViewControllerExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/QRCodeReaderViewControllerExample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QRCodeReaderViewController 3 | * 4 | * Copyright 2014-present Yannick Loriot. 5 | * http://yannickloriot.com 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | * 25 | */ 26 | 27 | #import 28 | 29 | @interface AppDelegate : UIResponder 30 | 31 | @property (strong, nonatomic) UIWindow *window; 32 | 33 | 34 | @end 35 | 36 | -------------------------------------------------------------------------------- /Example/QRCodeReaderViewControllerExample/AppDelegate.m: -------------------------------------------------------------------------------- 1 | /* 2 | * QRCodeReaderViewController 3 | * 4 | * Copyright 2014-present Yannick Loriot. 5 | * http://yannickloriot.com 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | * 25 | */ 26 | 27 | #import "AppDelegate.h" 28 | 29 | @interface AppDelegate () 30 | 31 | @end 32 | 33 | @implementation AppDelegate 34 | 35 | 36 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 37 | // Override point for customization after application launch. 38 | return YES; 39 | } 40 | 41 | - (void)applicationWillResignActive:(UIApplication *)application { 42 | // 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. 43 | // 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. 44 | } 45 | 46 | - (void)applicationDidEnterBackground:(UIApplication *)application { 47 | // 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. 48 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 49 | } 50 | 51 | - (void)applicationWillEnterForeground:(UIApplication *)application { 52 | // 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. 53 | } 54 | 55 | - (void)applicationDidBecomeActive:(UIApplication *)application { 56 | // 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. 57 | } 58 | 59 | - (void)applicationWillTerminate:(UIApplication *)application { 60 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 61 | } 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /Example/QRCodeReaderViewControllerExample/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Example/QRCodeReaderViewControllerExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | QRCode Reader 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.yannickloriot.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 3.5.1 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | Launch Screen 29 | UIMainStoryboardFile 30 | Main 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /Example/QRCodeReaderViewControllerExample/Launch Screen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 27 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /Example/QRCodeReaderViewControllerExample/ViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QRCodeReaderViewController 3 | * 4 | * Copyright 2014-present Yannick Loriot. 5 | * http://yannickloriot.com 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | * 25 | */ 26 | 27 | #import 28 | #import "QRCodeReaderDelegate.h" 29 | 30 | @interface ViewController : UIViewController 31 | 32 | - (IBAction)scanAction:(id)sender; 33 | 34 | @end 35 | 36 | -------------------------------------------------------------------------------- /Example/QRCodeReaderViewControllerExample/ViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | * QRCodeReaderViewController 3 | * 4 | * Copyright 2014-present Yannick Loriot. 5 | * http://yannickloriot.com 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | * 25 | */ 26 | 27 | #import "ViewController.h" 28 | #import "QRCodeReaderViewController.h" 29 | #import "QRCodeReader.h" 30 | 31 | @interface ViewController () 32 | 33 | @end 34 | 35 | @implementation ViewController 36 | 37 | - (IBAction)scanAction:(id)sender 38 | { 39 | if ([QRCodeReader supportsMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]]) { 40 | static QRCodeReaderViewController *reader = nil; 41 | static dispatch_once_t onceToken; 42 | 43 | dispatch_once(&onceToken, ^{ 44 | reader = [QRCodeReaderViewController new]; 45 | }); 46 | reader.delegate = self; 47 | 48 | [reader setCompletionWithBlock:^(NSString *resultAsString) { 49 | NSLog(@"Completion with result: %@", resultAsString); 50 | }]; 51 | 52 | [self presentViewController:reader animated:YES completion:NULL]; 53 | } 54 | else { 55 | UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Reader not supported by the current device" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; 56 | 57 | [alert show]; 58 | } 59 | } 60 | 61 | #pragma mark - QRCodeReader Delegate Methods 62 | 63 | - (void)reader:(QRCodeReaderViewController *)reader didScanResult:(NSString *)result 64 | { 65 | [self dismissViewControllerAnimated:YES completion:^{ 66 | UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"QRCodeReader" message:result delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; 67 | [alert show]; 68 | }]; 69 | } 70 | 71 | - (void)readerDidCancel:(QRCodeReaderViewController *)reader 72 | { 73 | [self dismissViewControllerAnimated:YES completion:NULL]; 74 | } 75 | 76 | @end 77 | -------------------------------------------------------------------------------- /Example/QRCodeReaderViewControllerExample/main.m: -------------------------------------------------------------------------------- 1 | /* 2 | * QRCodeReaderViewController 3 | * 4 | * Copyright 2014-present Yannick Loriot. 5 | * http://yannickloriot.com 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | * 25 | */ 26 | 27 | #import 28 | #import "AppDelegate.h" 29 | 30 | int main(int argc, char * argv[]) { 31 | @autoreleasepool { 32 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Example/QRCodeReaderViewControllerExampleTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.yannickloriot.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Example/QRCodeReaderViewControllerExampleTests/QRCodeReaderViewControllerExampleTests.m: -------------------------------------------------------------------------------- 1 | /* 2 | * QRCodeReaderViewController 3 | * 4 | * Copyright 2014-present Yannick Loriot. 5 | * http://yannickloriot.com 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | * 25 | */ 26 | 27 | #import 28 | #import 29 | 30 | @interface QRCodeReaderViewControllerExampleTests : XCTestCase 31 | 32 | @end 33 | 34 | @implementation QRCodeReaderViewControllerExampleTests 35 | 36 | - (void)setUp { 37 | [super setUp]; 38 | // Put setup code here. This method is called before the invocation of each test method in the class. 39 | } 40 | 41 | - (void)tearDown { 42 | // Put teardown code here. This method is called after the invocation of each test method in the class. 43 | [super tearDown]; 44 | } 45 | 46 | - (void)testExample { 47 | // This is an example of a functional test case. 48 | XCTAssert(YES, @"Pass"); 49 | } 50 | 51 | - (void)testPerformanceExample { 52 | // This is an example of a performance test case. 53 | [self measureBlock:^{ 54 | // Put the code you want to measure the time of here. 55 | }]; 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-present Yannick Loriot 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | 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, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /MQRCodeReaderViewController.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod spec lint MQRCodeReaderViewController.podspec' to ensure this is a 3 | # valid spec and to remove all comments including this before submitting the spec. 4 | # 5 | # To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html 6 | # To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/ 7 | # 8 | 9 | Pod::Spec.new do |s| 10 | 11 | # ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 12 | # 13 | # These will help people to find your library, and whilst it 14 | # can feel like a chore to fill in it's definitely to your advantage. The 15 | # summary should be tweet-length, and the description more in depth. 16 | # 17 | 18 | s.name = "MQRCodeReaderViewController" 19 | s.version = "0.0.1" 20 | s.summary = "A short description of MQRCodeReaderViewController." 21 | 22 | s.description = <<-DESC 23 | A longer description of MQRCodeReaderViewController in Markdown format. 24 | 25 | * Think: Why did you write this? What is the focus? What does it do? 26 | * CocoaPods will be using this to generate tags, and improve search results. 27 | * Try to keep it short, snappy and to the point. 28 | * Finally, don't worry about the indent, CocoaPods strips it! 29 | DESC 30 | 31 | s.homepage = "http://EXAMPLE/MQRCodeReaderViewController" 32 | # s.screenshots = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif" 33 | 34 | 35 | # ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 36 | # 37 | # Licensing your code is important. See http://choosealicense.com for more info. 38 | # CocoaPods will detect a license file if there is a named LICENSE* 39 | # Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'. 40 | # 41 | 42 | s.license = "MIT (example)" 43 | # s.license = { :type => "MIT", :file => "FILE_LICENSE" } 44 | 45 | 46 | # ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 47 | # 48 | # Specify the authors of the library, with email addresses. Email addresses 49 | # of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also 50 | # accepts just a name if you'd rather not provide an email address. 51 | # 52 | # Specify a social_media_url where others can refer to, for example a twitter 53 | # profile URL. 54 | # 55 | 56 | s.author = { "zhengjinghua" => "jin114001251@gmail.com" } 57 | # Or just: s.author = "zhengjinghua" 58 | # s.authors = { "zhengjinghua" => "jin114001251@gmail.com" } 59 | # s.social_media_url = "http://twitter.com/zhengjinghua" 60 | 61 | # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 62 | # 63 | # If this Pod runs only on iOS or OS X, then specify the platform and 64 | # the deployment target. You can optionally include the target after the platform. 65 | # 66 | 67 | # s.platform = :ios 68 | # s.platform = :ios, "5.0" 69 | 70 | # When using multiple platforms 71 | # s.ios.deployment_target = "5.0" 72 | # s.osx.deployment_target = "10.7" 73 | # s.watchos.deployment_target = "2.0" 74 | 75 | 76 | # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 77 | # 78 | # Specify the location from where the source should be retrieved. 79 | # Supports git, hg, bzr, svn and HTTP. 80 | # 81 | 82 | s.source = { :git => "http://EXAMPLE/MQRCodeReaderViewController.git", :tag => "0.0.1" } 83 | 84 | 85 | # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 86 | # 87 | # CocoaPods is smart about how it includes source code. For source files 88 | # giving a folder will include any swift, h, m, mm, c & cpp files. 89 | # For header files it will include any header in the folder. 90 | # Not including the public_header_files will make all headers public. 91 | # 92 | 93 | s.source_files = "Classes", "Classes/**/*.{h,m}" 94 | s.exclude_files = "Classes/Exclude" 95 | 96 | # s.public_header_files = "Classes/**/*.h" 97 | 98 | 99 | # ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 100 | # 101 | # A list of resources included with the Pod. These are copied into the 102 | # target bundle with a build phase script. Anything else will be cleaned. 103 | # You can preserve files from being cleaned, please don't preserve 104 | # non-essential files like tests, examples and documentation. 105 | # 106 | 107 | # s.resource = "icon.png" 108 | # s.resources = "Resources/*.png" 109 | 110 | # s.preserve_paths = "FilesToSave", "MoreFilesToSave" 111 | 112 | 113 | # ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 114 | # 115 | # Link your library with frameworks, or libraries. Libraries do not include 116 | # the lib prefix of their name. 117 | # 118 | 119 | # s.framework = "SomeFramework" 120 | # s.frameworks = "SomeFramework", "AnotherFramework" 121 | 122 | # s.library = "iconv" 123 | # s.libraries = "iconv", "xml2" 124 | 125 | 126 | # ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 127 | # 128 | # If your library depends on compiler flags you can set them in the xcconfig hash 129 | # where they will only apply to your library. If you depend on other Podspecs 130 | # you can include multiple dependencies to ensure it works. 131 | 132 | # s.requires_arc = true 133 | 134 | # s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" } 135 | # s.dependency "JSONKit", "~> 1.4" 136 | 137 | end 138 | -------------------------------------------------------------------------------- /QRCodeReaderViewController.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'QRCodeReaderViewController' 3 | s.version = '3.5.2' 4 | s.license = { :type => 'MIT', :file => 'LICENSE' } 5 | s.summary = 'Simple QRCode reader for iOS 7 and over' 6 | s.description = 'The `QRCodeReaderViewController` is a simple QRCode and bar code reader/scanner based on the `AVFoundation` framework from Apple. It aims to replace ZXing or ZBar for iOS 7 and over.' 7 | s.homepage = 'https://github.com/YannickL/QRCodeReaderViewController' 8 | s.authors = { 'Yannick Loriot' => 'contact@yannickloriot.com' } 9 | s.social_media_url = "https://twitter.com/yannickloriot" 10 | s.source = { :git => 'https://github.com/zhengjinghua/MQRCodeReaderViewController.git', 11 | :tag => s.version.to_s } 12 | s.requires_arc = true 13 | s.source_files = "QRCodeReaderViewController", "QRCodeReaderViewController/**/*.{h,m}" 14 | s.resources = "QRCodeReaderViewController/Resources/*.png" 15 | s.framework = 'AVFoundation' 16 | s.ios.deployment_target = '7.0' 17 | end 18 | 19 | -------------------------------------------------------------------------------- /QRCodeReaderViewController/QRCameraSwitchButton.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QRCodeReaderViewController 3 | * 4 | * Copyright 2014-present Yannick Loriot. 5 | * http://yannickloriot.com 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | * 25 | */ 26 | 27 | #import 28 | 29 | /** 30 | * The camera switch button. 31 | * @since 2.0.0 32 | */ 33 | @interface QRCameraSwitchButton : UIButton 34 | 35 | #pragma mark - Managing Properties 36 | /** @name Managing Properties */ 37 | 38 | /** 39 | * @abstract The edge color of the drawing. 40 | * @discussion The default color is the white. 41 | * @since 2.0.0 42 | */ 43 | @property (nonatomic, strong) UIColor *edgeColor; 44 | 45 | /** 46 | * @abstract The fill color of the drawing. 47 | * @discussion The default color is the darkgray. 48 | * @since 2.0.0 49 | */ 50 | @property (nonatomic, strong) UIColor *fillColor; 51 | 52 | /** 53 | * @abstract The edge color of the drawing when the button is touched. 54 | * @discussion The default color is the white. 55 | * @since 2.0.0 56 | */ 57 | @property (nonatomic, strong) UIColor *edgeHighlightedColor; 58 | 59 | /** 60 | * @abstract The fill color of the drawing when the button is touched. 61 | * @discussion The default color is the black. 62 | * @since 2.0.0 63 | */ 64 | @property (nonatomic, strong) UIColor *fillHighlightedColor; 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /QRCodeReaderViewController/QRCameraSwitchButton.m: -------------------------------------------------------------------------------- 1 | /* 2 | * QRCodeReaderViewController 3 | * 4 | * Copyright 2014-present Yannick Loriot. 5 | * http://yannickloriot.com 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | * 25 | */ 26 | 27 | #import "QRCameraSwitchButton.h" 28 | 29 | @implementation QRCameraSwitchButton 30 | 31 | - (id)initWithFrame:(CGRect)frame 32 | { 33 | if ((self = [super initWithFrame:frame])) { 34 | _edgeColor = [UIColor whiteColor]; 35 | _fillColor = [UIColor darkGrayColor]; 36 | _edgeHighlightedColor = [UIColor whiteColor]; 37 | _fillHighlightedColor = [UIColor blackColor]; 38 | } 39 | return self; 40 | } 41 | 42 | - (void)drawRect:(CGRect)rect 43 | { 44 | CGFloat width = rect.size.width; 45 | CGFloat height = rect.size.height; 46 | CGFloat center = width / 2; 47 | CGFloat middle = height / 2; 48 | 49 | CGFloat strokeLineWidth = 2; 50 | 51 | // Colors 52 | 53 | UIColor *paintColor = (self.state != UIControlStateHighlighted) ? _fillColor : _fillHighlightedColor; 54 | UIColor *strokeColor = (self.state != UIControlStateHighlighted) ? _edgeColor : _edgeHighlightedColor; 55 | 56 | // Camera box 57 | 58 | CGFloat cameraWidth = width * 0.4; 59 | CGFloat cameraHeight = cameraWidth * 0.6; 60 | CGFloat cameraX = center - cameraWidth / 2; 61 | CGFloat cameraY = middle - cameraHeight / 2; 62 | CGFloat cameraRadius = cameraWidth / 80; 63 | 64 | UIBezierPath *boxPath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(cameraX, cameraY, cameraWidth, cameraHeight) cornerRadius:cameraRadius]; 65 | 66 | // Camera lens 67 | 68 | CGFloat outerLensSize = cameraHeight * 0.8; 69 | CGFloat outerLensX = center - outerLensSize / 2; 70 | CGFloat outerLensY = middle - outerLensSize / 2; 71 | 72 | CGFloat innerLensSize = outerLensSize * 0.7; 73 | CGFloat innerLensX = center - innerLensSize / 2; 74 | CGFloat innerLensY = middle - innerLensSize / 2; 75 | 76 | UIBezierPath *outerLensPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(outerLensX, outerLensY, outerLensSize, outerLensSize)]; 77 | UIBezierPath *innerLensPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(innerLensX, innerLensY, innerLensSize, innerLensSize)]; 78 | 79 | // Draw flash box 80 | 81 | CGFloat flashBoxWidth = cameraWidth * 0.8; 82 | CGFloat flashBoxHeight = cameraHeight * 0.17; 83 | CGFloat flashBoxDeltaWidth = flashBoxWidth * 0.14; 84 | CGFloat flashLeftMostX = cameraX + (cameraWidth - flashBoxWidth) * 0.5; 85 | CGFloat flashBottomMostY = cameraY; 86 | 87 | UIBezierPath *flashPath = [UIBezierPath bezierPath]; 88 | [flashPath moveToPoint:CGPointMake(flashLeftMostX, flashBottomMostY)]; 89 | [flashPath addLineToPoint:CGPointMake(flashLeftMostX + flashBoxWidth, flashBottomMostY)]; 90 | [flashPath addLineToPoint:CGPointMake(flashLeftMostX + flashBoxWidth - flashBoxDeltaWidth, flashBottomMostY - flashBoxHeight)]; 91 | [flashPath addLineToPoint:CGPointMake(flashLeftMostX + flashBoxDeltaWidth, flashBottomMostY - flashBoxHeight)]; 92 | [flashPath closePath]; 93 | 94 | flashPath.lineCapStyle = kCGLineCapRound; 95 | flashPath.lineJoinStyle = kCGLineJoinRound; 96 | 97 | // Arrows 98 | 99 | CGFloat arrowHeadHeigth = cameraHeight * 0.5; 100 | CGFloat arrowHeadWidth = ((width - cameraWidth) / 2) * 0.3; 101 | CGFloat arrowTailHeigth = arrowHeadHeigth * 0.6; 102 | CGFloat arrowTailWidth = ((width - cameraWidth) / 2) * 0.7; 103 | 104 | // Draw left arrow 105 | 106 | CGFloat arrowLeftX = center - cameraWidth * 0.2; 107 | CGFloat arrowLeftY = middle + cameraHeight * 0.45; 108 | 109 | UIBezierPath *leftArrowPath = [UIBezierPath bezierPath]; 110 | [leftArrowPath moveToPoint:CGPointMake(arrowLeftX, arrowLeftY)]; 111 | [leftArrowPath addLineToPoint:CGPointMake(arrowLeftX - arrowHeadWidth, arrowLeftY - arrowHeadHeigth / 2)]; 112 | [leftArrowPath addLineToPoint:CGPointMake(arrowLeftX - arrowHeadWidth, arrowLeftY - arrowTailHeigth / 2)]; 113 | [leftArrowPath addLineToPoint:CGPointMake(arrowLeftX - arrowHeadWidth - arrowTailWidth, arrowLeftY - arrowTailHeigth / 2)]; 114 | [leftArrowPath addLineToPoint:CGPointMake(arrowLeftX - arrowHeadWidth - arrowTailWidth, arrowLeftY + arrowTailHeigth / 2)]; 115 | [leftArrowPath addLineToPoint:CGPointMake(arrowLeftX - arrowHeadWidth, arrowLeftY + arrowTailHeigth / 2)]; 116 | [leftArrowPath addLineToPoint:CGPointMake(arrowLeftX - arrowHeadWidth, arrowLeftY + arrowHeadHeigth / 2)]; 117 | [leftArrowPath closePath]; 118 | 119 | // Right arrow 120 | 121 | CGFloat arrowRightX = center + cameraWidth * 0.2; 122 | CGFloat arrowRightY = middle + cameraHeight * 0.60; 123 | 124 | UIBezierPath *rigthArrowPath = [UIBezierPath bezierPath]; 125 | [rigthArrowPath moveToPoint:CGPointMake(arrowRightX, arrowRightY)]; 126 | [rigthArrowPath addLineToPoint:CGPointMake(arrowRightX + arrowHeadWidth, arrowRightY - arrowHeadHeigth / 2)]; 127 | [rigthArrowPath addLineToPoint:CGPointMake(arrowRightX + arrowHeadWidth, arrowRightY - arrowTailHeigth / 2)]; 128 | [rigthArrowPath addLineToPoint:CGPointMake(arrowRightX + arrowHeadWidth + arrowTailWidth, arrowRightY - arrowTailHeigth / 2)]; 129 | [rigthArrowPath addLineToPoint:CGPointMake(arrowRightX + arrowHeadWidth + arrowTailWidth, arrowRightY + arrowTailHeigth / 2)]; 130 | [rigthArrowPath addLineToPoint:CGPointMake(arrowRightX + arrowHeadWidth, arrowRightY + arrowTailHeigth / 2)]; 131 | [rigthArrowPath addLineToPoint:CGPointMake(arrowRightX + arrowHeadWidth, arrowRightY + arrowHeadHeigth / 2)]; 132 | [rigthArrowPath closePath]; 133 | 134 | // Drawing 135 | 136 | [paintColor setFill]; 137 | [rigthArrowPath fill]; 138 | [strokeColor setStroke]; 139 | rigthArrowPath.lineWidth = strokeLineWidth; 140 | [rigthArrowPath stroke]; 141 | 142 | [paintColor setFill]; 143 | [boxPath fill]; 144 | [strokeColor setStroke]; 145 | boxPath.lineWidth = strokeLineWidth; 146 | [boxPath stroke]; 147 | 148 | [strokeColor setFill]; 149 | [outerLensPath fill]; 150 | 151 | [paintColor setFill]; 152 | [innerLensPath fill]; 153 | 154 | [paintColor setFill]; 155 | [flashPath fill]; 156 | [strokeColor setStroke]; 157 | flashPath.lineWidth = strokeLineWidth; 158 | [flashPath stroke]; 159 | 160 | [paintColor setFill]; 161 | [leftArrowPath fill]; 162 | [strokeColor setStroke]; 163 | leftArrowPath.lineWidth = strokeLineWidth; 164 | [leftArrowPath stroke]; 165 | } 166 | 167 | // MARK: - UIResponder Methods 168 | 169 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 170 | { 171 | [super touchesBegan:touches withEvent:event]; 172 | 173 | [self setNeedsDisplay]; 174 | } 175 | 176 | - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 177 | { 178 | [super touchesMoved:touches withEvent:event]; 179 | 180 | [self setNeedsDisplay]; 181 | } 182 | 183 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 184 | { 185 | [super touchesEnded:touches withEvent:event]; 186 | 187 | [self setNeedsDisplay]; 188 | } 189 | 190 | - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event 191 | { 192 | [super touchesCancelled:touches withEvent:event]; 193 | 194 | [self setNeedsDisplay]; 195 | } 196 | 197 | @end 198 | -------------------------------------------------------------------------------- /QRCodeReaderViewController/QRCodeReader.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QRCodeReader 3 | * 4 | * Copyright 2014-present Yannick Loriot. 5 | * http://yannickloriot.com 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | * 25 | */ 26 | 27 | #import 28 | #import 29 | #import 30 | 31 | /** 32 | * Reader object base on the `AVCaptureDevice` to read / scan 1D and 2D codes. 33 | */ 34 | @interface QRCodeReader : NSObject 35 | 36 | #pragma mark - Creating and Inializing QRCode Readers 37 | /** @name Creating and Inializing QRCode Readers */ 38 | 39 | /** 40 | * @abstract Initializes a reader with a list of metadata object types. 41 | * @param metadataObjectTypes An array of strings identifying the types of 42 | * metadata objects to process. 43 | * @since 3.0.0 44 | */ 45 | - (id)initWithMetadataObjectTypes:(NSArray *)metadataObjectTypes; 46 | 47 | /** 48 | * @abstract Creates a reader with a list of metadata object types. 49 | * @param metadataObjectTypes An array of strings identifying the types of 50 | * metadata objects to process. 51 | * @see initWithMetadataObjectTypes: 52 | * @since 3.0.0 53 | */ 54 | + (instancetype)readerWithMetadataObjectTypes:(NSArray *)metadataObjectTypes; 55 | 56 | #pragma mark - Checking the Reader Availabilities 57 | /** @name Checking the Reader Availabilities */ 58 | 59 | /** 60 | * @abstract Returns whether the reader is available with the current device. 61 | * @return a Boolean value indicating whether the reader is available. 62 | * @since 3.0.0 63 | */ 64 | + (BOOL)isAvailable; 65 | 66 | /** 67 | * @abstract Checks and return whether the given metadata object types are 68 | * supported by the current device. 69 | * @return a Boolean value indicating whether the given metadata object types 70 | * are supported by the current device. 71 | * @since 3.2.0 72 | */ 73 | + (BOOL)supportsMetadataObjectTypes:(NSArray *)metadataObjectTypes; 74 | 75 | #pragma mark - Checking the Metadata Items Types 76 | /** @name Checking the Metadata Items Types */ 77 | 78 | /** 79 | * @abstract An array of strings identifying the types of metadata objects to 80 | * process. 81 | * @since 3.0.0 82 | */ 83 | @property (strong, nonatomic, readonly) NSArray *metadataObjectTypes; 84 | 85 | #pragma mark - Viewing the Camera 86 | /** @name Viewing the Camera */ 87 | 88 | /** 89 | * @abstract CALayer that you use to display video as it is being captured 90 | * by an input device. 91 | * @since 3.0.0 92 | */ 93 | @property (strong, nonatomic, readonly) AVCaptureVideoPreviewLayer *previewLayer; 94 | 95 | #pragma mark - Controlling the Reader 96 | /** @name Controlling the Reader */ 97 | 98 | /** 99 | * @abstract Starts scanning the codes. 100 | * @since 3.0.0 101 | */ 102 | - (void)startScanning; 103 | 104 | /** 105 | * @abstract Stops scanning the codes. 106 | * @since 3.0.0 107 | */ 108 | - (void)stopScanning; 109 | 110 | /** 111 | * @abstract Indicates whether the session is currently running. 112 | * @discussion The value of this property is a Bool indicating whether the 113 | * receiver is running. 114 | * Clients can key value observe the value of this property to be notified 115 | * when the session automatically starts or stops running. 116 | * @since 3.3.0 117 | */ 118 | - (BOOL)running; 119 | 120 | /** 121 | * @abstract Switch between the back and the front camera. 122 | * @since 3.0.0 123 | */ 124 | - (void)switchDeviceInput; 125 | 126 | /** 127 | * @abstract Returns true whether a front device is available. 128 | * @return true whether a front device is available. 129 | * @since 3.0.0 130 | */ 131 | - (BOOL)hasFrontDevice; 132 | 133 | #pragma mark - Getting Inputs and Outputs 134 | /** @name Getting Inputs and Outputs */ 135 | 136 | /** 137 | * @abstract Accessing to the `AVCaptureDeviceInput` object representing 138 | * the default device input (generally the back camera). 139 | * @since 3.5.0 140 | */ 141 | @property (readonly) AVCaptureDeviceInput *defaultDeviceInput; 142 | 143 | /** 144 | * @abstract Accessing to the `AVCaptureDeviceInput` object representing 145 | * the front device input. 146 | * @since 3.5.0 147 | */ 148 | @property (readonly) AVCaptureDeviceInput *frontDeviceInput; 149 | 150 | /** 151 | * @abstract Accessing to the `AVCaptureMetadataOutput` object. 152 | * @discussion It allows you to configure the scanner to restrict the area of 153 | * the scan to the overlay one for example. 154 | * @since 3.5.0 155 | */ 156 | @property (readonly) AVCaptureMetadataOutput *metadataOutput; 157 | 158 | #pragma mark - Managing the Orientation 159 | /** @name Managing the Orientation */ 160 | 161 | /** 162 | * @abstract Returns the video orientation correspongind to the given interface 163 | * orientation. 164 | * @param interfaceOrientation An interface orientation. 165 | * @return the video orientation correspongind to the given device orientation. 166 | * @since 3.1.0 167 | */ 168 | + (AVCaptureVideoOrientation)videoOrientationFromInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation; 169 | 170 | #pragma mark - Managing the Block 171 | /** @name Managing the Block */ 172 | 173 | /** 174 | * @abstract Sets the completion with a block that executes when a QRCode 175 | * or when the user did stopped the scan. 176 | * @param completionBlock The block to be executed. This block has no 177 | * return value and takes one argument: the `resultAsString`. If the user 178 | * stop the scan and that there is no response the `resultAsString` argument 179 | * is nil. 180 | * @since 3.0.0 181 | */ 182 | - (void)setCompletionWithBlock:(void (^) (NSString *resultAsString))completionBlock; 183 | 184 | @end 185 | -------------------------------------------------------------------------------- /QRCodeReaderViewController/QRCodeReader.m: -------------------------------------------------------------------------------- 1 | /* 2 | * QRCodeReader 3 | * 4 | * Copyright 2014-present Yannick Loriot. 5 | * http://yannickloriot.com 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | * 25 | */ 26 | 27 | #import "QRCodeReader.h" 28 | 29 | @interface QRCodeReader () 30 | @property (strong, nonatomic) AVCaptureDevice *defaultDevice; 31 | @property (strong, nonatomic) AVCaptureDeviceInput *defaultDeviceInput; 32 | @property (strong, nonatomic) AVCaptureDevice *frontDevice; 33 | @property (strong, nonatomic) AVCaptureDeviceInput *frontDeviceInput; 34 | @property (strong, nonatomic) AVCaptureMetadataOutput *metadataOutput; 35 | @property (strong, nonatomic) AVCaptureSession *session; 36 | @property (strong, nonatomic) AVCaptureVideoPreviewLayer *previewLayer; 37 | 38 | @property (copy, nonatomic) void (^completionBlock) (NSString *); 39 | 40 | @end 41 | 42 | @implementation QRCodeReader 43 | 44 | - (id)initWithMetadataObjectTypes:(NSArray *)metadataObjectTypes 45 | { 46 | if ((self = [super init])) { 47 | _metadataObjectTypes = metadataObjectTypes; 48 | 49 | [self setupAVComponents]; 50 | [self configureDefaultComponents]; 51 | } 52 | return self; 53 | } 54 | 55 | + (instancetype)readerWithMetadataObjectTypes:(NSArray *)metadataObjectTypes 56 | { 57 | return [[self alloc] initWithMetadataObjectTypes:metadataObjectTypes]; 58 | } 59 | 60 | #pragma mark - Initializing the AV Components 61 | 62 | - (void)setupAVComponents 63 | { 64 | self.defaultDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 65 | 66 | if (_defaultDevice) { 67 | self.defaultDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:_defaultDevice error:nil]; 68 | self.metadataOutput = [[AVCaptureMetadataOutput alloc] init]; 69 | self.session = [[AVCaptureSession alloc] init]; 70 | self.previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.session]; 71 | 72 | for (AVCaptureDevice *device in [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]) { 73 | if (device.position == AVCaptureDevicePositionFront) { 74 | self.frontDevice = device; 75 | } 76 | } 77 | 78 | if (_frontDevice) { 79 | self.frontDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:_frontDevice error:nil]; 80 | } 81 | } 82 | } 83 | 84 | - (void)configureDefaultComponents 85 | { 86 | [_session addOutput:_metadataOutput]; 87 | 88 | if (_defaultDeviceInput) { 89 | [_session addInput:_defaultDeviceInput]; 90 | } 91 | 92 | [_metadataOutput setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()]; 93 | [_metadataOutput setMetadataObjectTypes:_metadataObjectTypes]; 94 | [_previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill]; 95 | } 96 | 97 | - (void)switchDeviceInput 98 | { 99 | if (_frontDeviceInput) { 100 | [_session beginConfiguration]; 101 | 102 | AVCaptureDeviceInput *currentInput = [_session.inputs firstObject]; 103 | [_session removeInput:currentInput]; 104 | 105 | AVCaptureDeviceInput *newDeviceInput = (currentInput.device.position == AVCaptureDevicePositionFront) ? _defaultDeviceInput : _frontDeviceInput; 106 | [_session addInput:newDeviceInput]; 107 | 108 | [_session commitConfiguration]; 109 | } 110 | } 111 | 112 | - (BOOL)hasFrontDevice 113 | { 114 | return _frontDevice != nil; 115 | } 116 | 117 | #pragma mark - Controlling Reader 118 | 119 | - (void)startScanning 120 | { 121 | if (![self.session isRunning]) { 122 | [self.session startRunning]; 123 | } 124 | } 125 | 126 | - (void)stopScanning 127 | { 128 | if ([self.session isRunning]) { 129 | [self.session stopRunning]; 130 | } 131 | } 132 | 133 | - (BOOL)running { 134 | return self.session.running; 135 | } 136 | 137 | #pragma mark - Managing the Orientation 138 | 139 | + (AVCaptureVideoOrientation)videoOrientationFromInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 140 | { 141 | switch (interfaceOrientation) { 142 | case UIInterfaceOrientationLandscapeLeft: 143 | return AVCaptureVideoOrientationLandscapeLeft; 144 | case UIInterfaceOrientationLandscapeRight: 145 | return AVCaptureVideoOrientationLandscapeRight; 146 | case UIInterfaceOrientationPortrait: 147 | return AVCaptureVideoOrientationPortrait; 148 | default: 149 | return AVCaptureVideoOrientationPortraitUpsideDown; 150 | } 151 | } 152 | 153 | #pragma mark - Checking the Reader Availabilities 154 | 155 | + (BOOL)isAvailable 156 | { 157 | @autoreleasepool { 158 | AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 159 | 160 | if (!captureDevice) { 161 | return NO; 162 | } 163 | 164 | NSError *error; 165 | AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error]; 166 | 167 | if (!deviceInput || error) { 168 | return NO; 169 | } 170 | 171 | return YES; 172 | } 173 | } 174 | 175 | + (BOOL)supportsMetadataObjectTypes:(NSArray *)metadataObjectTypes 176 | { 177 | if (![self isAvailable]) { 178 | return NO; 179 | } 180 | 181 | @autoreleasepool { 182 | // Setup components 183 | AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 184 | AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:nil]; 185 | AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init]; 186 | AVCaptureSession *session = [[AVCaptureSession alloc] init]; 187 | 188 | [session addInput:deviceInput]; 189 | [session addOutput:output]; 190 | 191 | if (metadataObjectTypes == nil || metadataObjectTypes.count == 0) { 192 | // Check the QRCode metadata object type by default 193 | metadataObjectTypes = @[AVMetadataObjectTypeQRCode]; 194 | } 195 | 196 | for (NSString *metadataObjectType in metadataObjectTypes) { 197 | if (![output.availableMetadataObjectTypes containsObject:metadataObjectType]) { 198 | return NO; 199 | } 200 | } 201 | 202 | return YES; 203 | } 204 | } 205 | 206 | #pragma mark - Managing the Block 207 | 208 | - (void)setCompletionWithBlock:(void (^) (NSString *resultAsString))completionBlock 209 | { 210 | self.completionBlock = completionBlock; 211 | } 212 | 213 | #pragma mark - AVCaptureMetadataOutputObjects Delegate Methods 214 | 215 | - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection 216 | { 217 | for (AVMetadataObject *current in metadataObjects) { 218 | if ([current isKindOfClass:[AVMetadataMachineReadableCodeObject class]] 219 | && [_metadataObjectTypes containsObject:current.type]) { 220 | NSString *scannedResult = [(AVMetadataMachineReadableCodeObject *) current stringValue]; 221 | 222 | if (_completionBlock) { 223 | _completionBlock(scannedResult); 224 | } 225 | 226 | break; 227 | } 228 | } 229 | } 230 | 231 | @end 232 | -------------------------------------------------------------------------------- /QRCodeReaderViewController/QRCodeReaderDelegate.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QRCodeReaderViewController 3 | * 4 | * Copyright 2014-present Yannick Loriot. 5 | * http://yannickloriot.com 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | * 25 | */ 26 | 27 | @class QRCodeReaderViewController; 28 | 29 | /** 30 | * This protocol defines delegate methods for objects that implements the 31 | * `QRCodeReaderDelegate`. The methods of the protocol allow the delegate to be 32 | * notified when the reader did scan result and or when the user wants to stop 33 | * to read some QRCodes. 34 | */ 35 | @protocol QRCodeReaderDelegate 36 | 37 | @optional 38 | 39 | #pragma mark - Listening for Reader Status 40 | /** @name Listening for Reader Status */ 41 | 42 | /** 43 | * @abstract Tells the delegate that the reader did scan a QRCode. 44 | * @param reader The reader view controller that scanned a QRCode. 45 | * @param result The content of the QRCode as a string. 46 | * @since 1.0.0 47 | */ 48 | - (void)reader:(QRCodeReaderViewController *)reader didScanResult:(NSString *)result; 49 | 50 | /** 51 | * @abstract Tells the delegate that the user wants to stop scanning QRCodes. 52 | * @param reader The reader view controller that the user wants to stop. 53 | * @since 1.0.0 54 | */ 55 | - (void)readerDidCancel:(QRCodeReaderViewController *)reader; 56 | 57 | @end -------------------------------------------------------------------------------- /QRCodeReaderViewController/QRCodeReaderView/QRCodeReaderAanimationLineView.h: -------------------------------------------------------------------------------- 1 | // 2 | // QRCodeReaderAanimationLineView.h 3 | // QRCodeReaderViewControllerExample 4 | // 5 | // Created by Jin on 9/24/15. 6 | // Copyright © 2015 Yannick Loriot. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //static const float AnimationLineMinY = 185; 12 | //static const float AnimationLineMaxY = 485; 13 | 14 | @interface QRCodeReaderAanimationLineView : UIImageView 15 | 16 | - (instancetype)initWithFrame:(CGRect)frame minY:(float)minY maxY:(float)maxY; 17 | - (void)startAnimation; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /QRCodeReaderViewController/QRCodeReaderView/QRCodeReaderAanimationLineView.m: -------------------------------------------------------------------------------- 1 | // 2 | // QRCodeReaderAanimationLineView.m 3 | // QRCodeReaderViewControllerExample 4 | // 5 | // Created by Jin on 9/24/15. 6 | // Copyright © 2015 Yannick Loriot. All rights reserved. 7 | // 8 | 9 | #import "QRCodeReaderAanimationLineView.h" 10 | 11 | @interface QRCodeReaderAanimationLineView () 12 | @property (nonatomic) float minY; 13 | @property (nonatomic) float maxY; 14 | @end 15 | 16 | @implementation QRCodeReaderAanimationLineView 17 | 18 | - (instancetype)initWithFrame:(CGRect)frame minY:(float)minY maxY:(float)maxY { 19 | if (self = [super initWithFrame:frame]) { 20 | _minY = minY; 21 | _maxY = maxY; 22 | [self setup]; 23 | } 24 | 25 | return self; 26 | } 27 | 28 | - (void)setup { 29 | self.image = [UIImage imageNamed:@"QRCodeLine"]; 30 | } 31 | 32 | - (void)startAnimation 33 | { 34 | __block CGRect frame = self.frame; 35 | 36 | static BOOL flag = YES; 37 | 38 | if (flag) 39 | { 40 | frame.origin.y = self.minY; 41 | flag = NO; 42 | 43 | [UIView animateWithDuration:1.0 / 50 animations:^{ 44 | 45 | frame.origin.y += 2; 46 | self.frame = frame; 47 | 48 | } completion:nil]; 49 | } 50 | else 51 | { 52 | if (self.frame.origin.y >= self.minY) 53 | { 54 | if (self.frame.origin.y >= self.maxY - 12) 55 | { 56 | frame.origin.y = self.minY; 57 | self.frame = frame; 58 | 59 | flag = YES; 60 | } 61 | else 62 | { 63 | [UIView animateWithDuration:1.0 / 50 animations:^{ 64 | 65 | frame.origin.y += 2; 66 | self.frame = frame; 67 | 68 | } completion:nil]; 69 | } 70 | } 71 | else 72 | { 73 | flag = !flag; 74 | } 75 | } 76 | 77 | } 78 | 79 | 80 | @end 81 | -------------------------------------------------------------------------------- /QRCodeReaderViewController/QRCodeReaderView/QRCodeReaderMaskView.h: -------------------------------------------------------------------------------- 1 | // 2 | // QRCodeReaderMaskView.h 3 | // QRCodeReaderViewControllerExample 4 | // 5 | // Created by Jin on 9/24/15. 6 | // Copyright © 2015 Yannick Loriot. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface QRCodeReaderMaskView : UIView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /QRCodeReaderViewController/QRCodeReaderView/QRCodeReaderMaskView.m: -------------------------------------------------------------------------------- 1 | // 2 | // QRCodeReaderMaskView.m 3 | // QRCodeReaderViewControllerExample 4 | // 5 | // Created by Jin on 9/24/15. 6 | // Copyright © 2015 Yannick Loriot. All rights reserved. 7 | // 8 | 9 | #import "QRCodeReaderMaskView.h" 10 | 11 | @implementation QRCodeReaderMaskView 12 | 13 | - (instancetype)initWithFrame:(CGRect)frame { 14 | if (self = [super initWithFrame:frame]) { 15 | [self setup]; 16 | } 17 | 18 | return self; 19 | } 20 | 21 | - (void)setup { 22 | self.alpha = 0.5; 23 | self.backgroundColor = [UIColor blackColor]; 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /QRCodeReaderViewController/QRCodeReaderView/QRCodeReaderView.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QRCodeReaderViewController 3 | * 4 | * Copyright 2014-present Yannick Loriot. 5 | * http://yannickloriot.com 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | * 25 | */ 26 | 27 | #import 28 | 29 | /** 30 | * Overlay over the camera view to display the area (a square) where to scan the 31 | * code. 32 | * @since 2.0.0 33 | */ 34 | @interface QRCodeReaderView : UIView 35 | 36 | - (void)startScanning; 37 | - (void)stopScanning; 38 | @end 39 | -------------------------------------------------------------------------------- /QRCodeReaderViewController/QRCodeReaderView/QRCodeReaderView.m: -------------------------------------------------------------------------------- 1 | /* 2 | * QRCodeReaderViewController 3 | * 4 | * Copyright 2014-present Yannick Loriot. 5 | * http://yannickloriot.com 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | * 25 | */ 26 | 27 | 28 | #import "QRCodeReaderView.h" 29 | #import "QRCodeReaderMaskView.h" 30 | #import "QRCodeReaderAanimationLineView.h" 31 | 32 | #define DeviceWidth [UIScreen mainScreen].bounds.size.width 33 | #define DeviceHeight [UIScreen mainScreen].bounds.size.height 34 | #define DeviceFrame [UIScreen mainScreen].bounds 35 | 36 | static const float CancelButtonHeight = 40; 37 | static const float ReaderViewLengthRatio = 0.72; 38 | 39 | @interface QRCodeReaderView () 40 | @property (nonatomic, strong) QRCodeReaderAanimationLineView *animationLine; 41 | @property (nonatomic, strong) NSTimer *lineTimer; 42 | @property (nonatomic) QRCodeReaderMaskView *maskView; 43 | 44 | @property (nonatomic) float animationLineMaxY; 45 | @property (nonatomic) float animationLineMinY; 46 | @property (nonatomic) float readerViewSideLength; 47 | @end 48 | 49 | @implementation QRCodeReaderView 50 | 51 | - (id)initWithFrame:(CGRect)frame 52 | { 53 | if ((self = [super initWithFrame:frame])) { 54 | [self initSettingValue]; 55 | [self setOverlayPickerView]; 56 | } 57 | 58 | return self; 59 | } 60 | 61 | - (void)initSettingValue { 62 | _readerViewSideLength = DeviceWidth * ReaderViewLengthRatio; 63 | _animationLineMinY = (DeviceHeight - 20 - _readerViewSideLength - CancelButtonHeight) / 2; 64 | _animationLineMaxY = _animationLineMinY + _readerViewSideLength; 65 | } 66 | 67 | - (QRCodeReaderAanimationLineView *)animationLine { 68 | if(_animationLine == nil) { 69 | _animationLine = [[QRCodeReaderAanimationLineView alloc] initWithFrame:CGRectMake((DeviceWidth - _readerViewSideLength) / 2, 0, _readerViewSideLength, 12 * self.readerViewSideLength / DeviceWidth) minY:self.animationLineMinY maxY:self.animationLineMaxY]; 70 | } 71 | return _animationLine; 72 | } 73 | 74 | #pragma mark - Private Methods 75 | - (void)setOverlayPickerView 76 | { 77 | // Add line in the middle. 78 | [self addSubview:self.animationLine]; 79 | 80 | // Add mask view 81 | UIView* maskTopView = [[QRCodeReaderMaskView alloc] initWithFrame:CGRectMake(0, 0, DeviceWidth, self.animationLineMinY)]; 82 | [self addSubview:maskTopView]; 83 | 84 | UIView *maskLeftView = [[QRCodeReaderMaskView alloc] initWithFrame:CGRectMake(0, self.animationLineMinY, (DeviceWidth - self.readerViewSideLength) / 2.0, self.readerViewSideLength)]; 85 | [self addSubview:maskLeftView]; 86 | 87 | UIView *maskRightView = [[QRCodeReaderMaskView alloc] initWithFrame:CGRectMake(DeviceWidth - CGRectGetMaxX(maskLeftView.frame), self.animationLineMinY, CGRectGetMaxX(maskLeftView.frame), self.readerViewSideLength)]; 88 | [self addSubview:maskRightView]; 89 | 90 | CGFloat space_h = DeviceHeight - self.animationLineMaxY; 91 | 92 | UIView *maskBottomView = [[QRCodeReaderMaskView alloc] initWithFrame:CGRectMake(0, self.animationLineMaxY, DeviceWidth, space_h)]; 93 | [self addSubview:maskBottomView]; 94 | 95 | CGFloat scanCropViewWidth = DeviceWidth - 2 * CGRectGetMaxX(maskLeftView.frame) + 1; 96 | UIView *scanCropView = [[UIView alloc] initWithFrame:CGRectMake((DeviceWidth - scanCropViewWidth)/2, self.animationLineMinY-1.0, scanCropViewWidth, self.readerViewSideLength + 2)]; 97 | scanCropView.layer.borderColor = [UIColor whiteColor].CGColor; 98 | scanCropView.layer.borderWidth = 1.0; 99 | [self addSubview:scanCropView]; 100 | 101 | // Add cornet Image 102 | UIImage *cornerImage = [UIImage imageNamed:@"QRCodeTopLeft"]; 103 | UIImageView *topLeftImageView = [[UIImageView alloc] initWithFrame:CGRectMake(CGRectGetMaxX(maskLeftView.frame) - 1.0, CGRectGetMaxY(maskTopView.frame) - 1.0, cornerImage.size.width, cornerImage.size.height)]; 104 | topLeftImageView.image = cornerImage; 105 | [self addSubview:topLeftImageView]; 106 | 107 | cornerImage = [UIImage imageNamed:@"QRCodeTopRight"]; 108 | UIImageView *topRightImage = [[UIImageView alloc] initWithFrame:CGRectMake(CGRectGetMinX(maskRightView.frame) - cornerImage.size.width + 1.0, CGRectGetMaxY(maskTopView.frame) - 1.0, cornerImage.size.width, cornerImage.size.height)]; 109 | topRightImage.image = cornerImage; 110 | [self addSubview:topRightImage]; 111 | 112 | cornerImage = [UIImage imageNamed:@"QRCodeBottomLeft"]; 113 | UIImageView *bottomLeftImage = [[UIImageView alloc] initWithFrame:CGRectMake(CGRectGetMaxX(maskLeftView.frame) - 1.0, CGRectGetMinY(maskBottomView.frame) - cornerImage.size.height + 2.0, cornerImage.size.width, cornerImage.size.height)]; 114 | bottomLeftImage.image = cornerImage; 115 | [self addSubview:bottomLeftImage]; 116 | 117 | cornerImage = [UIImage imageNamed:@"QRCodeBottomRight"]; 118 | UIImageView *bottomRightImage = [[UIImageView alloc] initWithFrame:CGRectMake(CGRectGetMinX(maskRightView.frame) - cornerImage.size.width + 1.0, CGRectGetMinY(maskBottomView.frame) - cornerImage.size.height + 2.0, cornerImage.size.width, cornerImage.size.height)]; 119 | bottomRightImage.image = cornerImage; 120 | [self addSubview:bottomRightImage]; 121 | 122 | //说明label 123 | UILabel *labIntroudction = [[UILabel alloc] init]; 124 | labIntroudction.backgroundColor = [UIColor clearColor]; 125 | labIntroudction.frame = CGRectMake(CGRectGetMaxX(maskLeftView.frame), CGRectGetMinY(maskBottomView.frame) + 25, self.readerViewSideLength, 20); 126 | labIntroudction.textAlignment = NSTextAlignmentCenter; 127 | labIntroudction.font = [UIFont boldSystemFontOfSize:13.0]; 128 | labIntroudction.textColor = [UIColor whiteColor]; 129 | labIntroudction.text = @"将二维码置于框内, 即可自动扫描"; 130 | [self addSubview:labIntroudction]; 131 | 132 | 133 | } 134 | 135 | - (void)startScanning 136 | { 137 | _lineTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 / 50 target:self selector:@selector(animationForLine) userInfo:nil repeats:YES]; 138 | } 139 | 140 | - (void)stopScanning 141 | { 142 | if (_lineTimer) 143 | { 144 | [_lineTimer invalidate]; 145 | _lineTimer = nil; 146 | } 147 | 148 | } 149 | 150 | - (void)animationForLine 151 | { 152 | [self.animationLine startAnimation]; 153 | } 154 | 155 | @end 156 | -------------------------------------------------------------------------------- /QRCodeReaderViewController/QRCodeReaderViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QRCodeReaderViewController 3 | * 4 | * Copyright 2014-present Yannick Loriot. 5 | * http://yannickloriot.com 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | * 25 | */ 26 | 27 | #import 28 | #import "QRCodeReaderDelegate.h" 29 | #import "QRCodeReader.h" 30 | 31 | /** 32 | * Convenient controller to display a view to scan/read 1D or 2D bar codes like 33 | * the QRCodes. It is based on the `AVFoundation` framework from Apple. It aims 34 | * to replace ZXing or ZBar for iOS 7 and over. 35 | */ 36 | @interface QRCodeReaderViewController : UIViewController 37 | 38 | #pragma mark - Creating and Inializing QRCodeReader Controllers 39 | /** @name Creating and Inializing QRCode Reader Controllers */ 40 | 41 | /** 42 | * @abstract Initializes a view controller to read QRCodes from a displayed 43 | * video preview and a cancel button to be go back. 44 | * @param cancelTitle The title of the cancel button. 45 | * @discussion This convenient method is used to instanciate a reader with 46 | * only one supported metadata object types: the QRCode. 47 | * @see initWithCancelButtonTitle:metadataObjectTypes: 48 | * @since 1.0.0 49 | */ 50 | - (nonnull id)initWithCancelButtonTitle:(nullable NSString *)cancelTitle; 51 | 52 | /** 53 | * @abstract Creates a view controller to read QRCodes from a displayed 54 | * video preview and a cancel button to be go back. 55 | * @param cancelTitle The title of the cancel button. 56 | * @see initWithCancelButtonTitle: 57 | * @since 1.0.0 58 | */ 59 | + (nonnull instancetype)readerWithCancelButtonTitle:(nullable NSString *)cancelTitle; 60 | 61 | /** 62 | * @abstract Initializes a reader view controller with a list of metadata 63 | * object types. 64 | * @param metadataObjectTypes An array of strings identifying the types of 65 | * metadata objects to process. 66 | * @see initWithCancelButtonTitle:metadataObjectTypes: 67 | * @since 3.0.0 68 | */ 69 | - (nonnull id)initWithMetadataObjectTypes:(nonnull NSArray *)metadataObjectTypes; 70 | 71 | /** 72 | * @abstract Creates a reader view controller with a list of metadata object 73 | * types. 74 | * @param metadataObjectTypes An array of strings identifying the types of 75 | * metadata objects to process. 76 | * @see initWithMetadataObjectTypes: 77 | * @since 3.0.0 78 | */ 79 | + (nonnull instancetype)readerWithMetadataObjectTypes:(nonnull NSArray *)metadataObjectTypes; 80 | 81 | /** 82 | * @abstract Initializes a view controller to read wanted metadata object 83 | * types from a displayed video preview and a cancel button to be go back. 84 | * @param cancelTitle The title of the cancel button. 85 | * @param metadataObjectTypes The type (“symbology”) of barcode to scan. 86 | * @see initWithCancelButtonTitle:codeReader: 87 | * @since 2.0.0 88 | */ 89 | - (nonnull id)initWithCancelButtonTitle:(nullable NSString *)cancelTitle metadataObjectTypes:(nonnull NSArray *)metadataObjectTypes; 90 | 91 | /** 92 | * @abstract Creates a view controller to read wanted metadata object types 93 | * from a displayed video preview and a cancel button to be go back. 94 | * @param cancelTitle The title of the cancel button. 95 | * @param metadataObjectTypes The type (“symbology”) of barcode to scan. 96 | * @see initWithCancelButtonTitle:metadataObjectTypes: 97 | * @since 2.0.0 98 | */ 99 | + (nonnull instancetype)readerWithCancelButtonTitle:(nullable NSString *)cancelTitle metadataObjectTypes:(nonnull NSArray *)metadataObjectTypes; 100 | 101 | /** 102 | * @abstract Initializes a view controller using a cancel button title and 103 | * a code reader. 104 | * @param cancelTitle The title of the cancel button. 105 | * @param codeReader The reader to decode the codes. 106 | * @see initWithCancelButtonTitle:codeReader:startScanningAtLoad: 107 | * @since 3.0.0 108 | */ 109 | - (nonnull id)initWithCancelButtonTitle:(nullable NSString *)cancelTitle codeReader:(nonnull QRCodeReader *)codeReader; 110 | 111 | /** 112 | * @abstract Initializes a view controller using a cancel button title and 113 | * a code reader. 114 | * @param cancelTitle The title of the cancel button. 115 | * @param codeReader The reader to decode the codes. 116 | * @see initWithCancelButtonTitle:codeReader: 117 | * @since 3.0.0 118 | */ 119 | + (nonnull instancetype)readerWithCancelButtonTitle:(nullable NSString *)cancelTitle codeReader:(nonnull QRCodeReader *)codeReader; 120 | 121 | /** 122 | * @abstract Initializes a view controller using a cancel button title and 123 | * a code reader. 124 | * @param cancelTitle The title of the cancel button. 125 | * @param codeReader The reader to decode the codes. 126 | * @param startScanningAtLoad Flag to know whether the view controller start scanning the codes when the view will appear. 127 | * @since 3.0.0 128 | */ 129 | - (nonnull id)initWithCancelButtonTitle:(nullable NSString *)cancelTitle codeReader:(nonnull QRCodeReader *)codeReader startScanningAtLoad:(BOOL)startScanningAtLoad; 130 | 131 | /** 132 | * @abstract Initializes a view controller using a cancel button title and 133 | * a code reader. 134 | * @param cancelTitle The title of the cancel button. 135 | * @param codeReader The reader to decode the codes. 136 | * @param startScanningAtLoad Flag to know whether the view controller start scanning the codes when the view will appear. 137 | * @see initWithCancelButtonTitle:codeReader:startScanningAtLoad: 138 | * @since 3.0.0 139 | */ 140 | + (nonnull instancetype)readerWithCancelButtonTitle:(nullable NSString *)cancelTitle codeReader:(nonnull QRCodeReader *)codeReader startScanningAtLoad:(BOOL)startScanningAtLoad; 141 | 142 | #pragma mark - Controlling the Reader 143 | /** @name Controlling the Reader */ 144 | 145 | /** 146 | * @abstract Starts scanning the codes. 147 | * @since 3.0.0 148 | */ 149 | - (void)startScanning; 150 | 151 | /** 152 | * @abstract Stops scanning the codes. 153 | * @since 3.0.0 154 | */ 155 | - (void)stopScanning; 156 | 157 | #pragma mark - Managing the Delegate 158 | /** @name Managing the Delegate */ 159 | 160 | /** 161 | * @abstract The object that acts as the delegate of the receiving QRCode 162 | * reader. 163 | * @since 1.0.0 164 | */ 165 | @property (nonatomic, weak) id __nullable delegate; 166 | 167 | /** 168 | * @abstract Sets the completion with a block that executes when a QRCode 169 | * or when the user did stopped the scan. 170 | * @param completionBlock The block to be executed. This block has no 171 | * return value and takes one argument: the `resultAsString`. If the user 172 | * stop the scan and that there is no response the `resultAsString` argument 173 | * is nil. 174 | * @since 1.0.1 175 | */ 176 | - (void)setCompletionWithBlock:(nullable void (^) (NSString * __nullable resultAsString))completionBlock; 177 | 178 | #pragma mark - Managing the Reader 179 | /** @name Managing the Reader */ 180 | 181 | /** 182 | * @abstract The default code reader created with the controller. 183 | * @since 3.0.0 184 | */ 185 | @property (strong, nonatomic, readonly) QRCodeReader * __nonnull codeReader; 186 | 187 | @end 188 | -------------------------------------------------------------------------------- /QRCodeReaderViewController/QRCodeReaderViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | * QRCodeReaderViewController 3 | * 4 | * Copyright 2014-present Yannick Loriot. 5 | * http://yannickloriot.com 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | * 25 | */ 26 | 27 | #import "QRCodeReaderViewController.h" 28 | #import "QRCameraSwitchButton.h" 29 | #import "QRCodeReaderView.h" 30 | 31 | @interface QRCodeReaderViewController () 32 | @property (strong, nonatomic) QRCameraSwitchButton *switchCameraButton; 33 | @property (strong, nonatomic) QRCodeReaderView *cameraView; 34 | @property (strong, nonatomic) UIButton *cancelButton; 35 | @property (strong, nonatomic) QRCodeReader *codeReader; 36 | @property (assign, nonatomic) BOOL startScanningAtLoad; 37 | 38 | @property (copy, nonatomic) void (^completionBlock) (NSString * __nullable); 39 | 40 | @end 41 | 42 | @implementation QRCodeReaderViewController 43 | 44 | - (void)dealloc 45 | { 46 | [self stopScanning]; 47 | 48 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 49 | } 50 | 51 | - (id)init 52 | { 53 | return [self initWithCancelButtonTitle:nil]; 54 | } 55 | 56 | - (id)initWithCancelButtonTitle:(NSString *)cancelTitle 57 | { 58 | return [self initWithCancelButtonTitle:cancelTitle metadataObjectTypes:@[AVMetadataObjectTypeQRCode]]; 59 | } 60 | 61 | - (id)initWithMetadataObjectTypes:(NSArray *)metadataObjectTypes 62 | { 63 | return [self initWithCancelButtonTitle:nil metadataObjectTypes:metadataObjectTypes]; 64 | } 65 | 66 | - (id)initWithCancelButtonTitle:(NSString *)cancelTitle metadataObjectTypes:(NSArray *)metadataObjectTypes 67 | { 68 | QRCodeReader *reader = [QRCodeReader readerWithMetadataObjectTypes:metadataObjectTypes]; 69 | 70 | return [self initWithCancelButtonTitle:cancelTitle codeReader:reader]; 71 | } 72 | 73 | - (id)initWithCancelButtonTitle:(NSString *)cancelTitle codeReader:(QRCodeReader *)codeReader 74 | { 75 | return [self initWithCancelButtonTitle:cancelTitle codeReader:codeReader startScanningAtLoad:true]; 76 | } 77 | 78 | - (id)initWithCancelButtonTitle:(NSString *)cancelTitle codeReader:(QRCodeReader *)codeReader startScanningAtLoad:(BOOL)startScanningAtLoad 79 | { 80 | if ((self = [super init])) { 81 | self.view.backgroundColor = [UIColor blackColor]; 82 | self.codeReader = codeReader; 83 | self.startScanningAtLoad = startScanningAtLoad; 84 | 85 | if (cancelTitle == nil) { 86 | cancelTitle = NSLocalizedString(@"Cancel", @"Cancel"); 87 | } 88 | 89 | [self setupUIComponentsWithCancelButtonTitle:cancelTitle]; 90 | [self setupAutoLayoutConstraints]; 91 | 92 | [_cameraView.layer insertSublayer:_codeReader.previewLayer atIndex:0]; 93 | 94 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil]; 95 | 96 | __weak typeof(self) weakSelf = self; 97 | 98 | [codeReader setCompletionWithBlock:^(NSString *resultAsString) { 99 | if (weakSelf.completionBlock != nil) { 100 | weakSelf.completionBlock(resultAsString); 101 | } 102 | 103 | if (weakSelf.delegate && [weakSelf.delegate respondsToSelector:@selector(reader:didScanResult:)]) { 104 | [weakSelf.delegate reader:weakSelf didScanResult:resultAsString]; 105 | } 106 | }]; 107 | } 108 | return self; 109 | } 110 | 111 | + (instancetype)readerWithCancelButtonTitle:(NSString *)cancelTitle 112 | { 113 | return [[self alloc] initWithCancelButtonTitle:cancelTitle]; 114 | } 115 | 116 | + (instancetype)readerWithMetadataObjectTypes:(NSArray *)metadataObjectTypes 117 | { 118 | return [[self alloc] initWithMetadataObjectTypes:metadataObjectTypes]; 119 | } 120 | 121 | + (instancetype)readerWithCancelButtonTitle:(NSString *)cancelTitle metadataObjectTypes:(NSArray *)metadataObjectTypes 122 | { 123 | return [[self alloc] initWithCancelButtonTitle:cancelTitle metadataObjectTypes:metadataObjectTypes]; 124 | } 125 | 126 | + (instancetype)readerWithCancelButtonTitle:(NSString *)cancelTitle codeReader:(QRCodeReader *)codeReader 127 | { 128 | return [[self alloc] initWithCancelButtonTitle:cancelTitle codeReader:codeReader]; 129 | } 130 | 131 | + (instancetype)readerWithCancelButtonTitle:(NSString *)cancelTitle codeReader:(QRCodeReader *)codeReader startScanningAtLoad:(BOOL)startScanningAtLoad 132 | { 133 | return [[self alloc] initWithCancelButtonTitle:cancelTitle codeReader:codeReader startScanningAtLoad:startScanningAtLoad]; 134 | } 135 | 136 | - (void)viewWillAppear:(BOOL)animated 137 | { 138 | [super viewWillAppear:animated]; 139 | 140 | if (_startScanningAtLoad) { 141 | [self startScanning]; 142 | } 143 | } 144 | 145 | - (void)viewWillDisappear:(BOOL)animated 146 | { 147 | [self stopScanning]; 148 | 149 | [super viewWillDisappear:animated]; 150 | } 151 | 152 | - (void)viewWillLayoutSubviews 153 | { 154 | [super viewWillLayoutSubviews]; 155 | 156 | _codeReader.previewLayer.frame = self.view.bounds; 157 | } 158 | 159 | - (BOOL)shouldAutorotate 160 | { 161 | return YES; 162 | } 163 | 164 | #pragma mark - Controlling the Reader 165 | 166 | - (void)startScanning { 167 | [_codeReader startScanning]; 168 | 169 | [_cameraView startScanning]; 170 | } 171 | 172 | - (void)stopScanning { 173 | [_codeReader stopScanning]; 174 | 175 | [_cameraView stopScanning]; 176 | } 177 | 178 | #pragma mark - Managing the Orientation 179 | 180 | - (void)orientationChanged:(NSNotification *)notification 181 | { 182 | [_cameraView setNeedsDisplay]; 183 | 184 | if (_codeReader.previewLayer.connection.isVideoOrientationSupported) { 185 | UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; 186 | 187 | _codeReader.previewLayer.connection.videoOrientation = [QRCodeReader videoOrientationFromInterfaceOrientation: 188 | orientation]; 189 | } 190 | } 191 | 192 | #pragma mark - Managing the Block 193 | 194 | - (void)setCompletionWithBlock:(void (^) (NSString *resultAsString))completionBlock 195 | { 196 | self.completionBlock = completionBlock; 197 | } 198 | 199 | #pragma mark - Initializing the AV Components 200 | 201 | - (void)setupUIComponentsWithCancelButtonTitle:(NSString *)cancelButtonTitle 202 | { 203 | self.cameraView = [[QRCodeReaderView alloc] init]; 204 | _cameraView.translatesAutoresizingMaskIntoConstraints = NO; 205 | _cameraView.clipsToBounds = YES; 206 | [self.view addSubview:_cameraView]; 207 | 208 | [_codeReader.previewLayer setFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)]; 209 | 210 | if ([_codeReader.previewLayer.connection isVideoOrientationSupported]) { 211 | UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; 212 | 213 | _codeReader.previewLayer.connection.videoOrientation = [QRCodeReader videoOrientationFromInterfaceOrientation:orientation]; 214 | } 215 | 216 | self.cancelButton = [[UIButton alloc] init]; 217 | _cancelButton.translatesAutoresizingMaskIntoConstraints = NO; 218 | [_cancelButton setTitle:cancelButtonTitle forState:UIControlStateNormal]; 219 | [_cancelButton setTitleColor:[UIColor grayColor] forState:UIControlStateHighlighted]; 220 | [_cancelButton addTarget:self action:@selector(cancelAction:) forControlEvents:UIControlEventTouchUpInside]; 221 | [self.view addSubview:_cancelButton]; 222 | } 223 | 224 | - (void)setupAutoLayoutConstraints 225 | { 226 | NSDictionary *views = NSDictionaryOfVariableBindings(_cameraView, _cancelButton); 227 | 228 | [self.view addConstraints: 229 | [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_cameraView][_cancelButton(40)]|" options:0 metrics:nil views:views]]; 230 | [self.view addConstraints: 231 | [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_cameraView]|" options:0 metrics:nil views:views]]; 232 | [self.view addConstraints: 233 | [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_cancelButton]-|" options:0 metrics:nil views:views]]; 234 | 235 | if (_switchCameraButton) { 236 | NSDictionary *switchViews = NSDictionaryOfVariableBindings(_switchCameraButton); 237 | 238 | [self.view addConstraints: 239 | [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_switchCameraButton(50)]" options:0 metrics:nil views:switchViews]]; 240 | [self.view addConstraints: 241 | [NSLayoutConstraint constraintsWithVisualFormat:@"H:[_switchCameraButton(70)]|" options:0 metrics:nil views:switchViews]]; 242 | } 243 | } 244 | 245 | - (void)switchDeviceInput 246 | { 247 | [_codeReader switchDeviceInput]; 248 | } 249 | 250 | #pragma mark - Catching Button Events 251 | 252 | - (void)cancelAction:(UIButton *)button 253 | { 254 | [_codeReader stopScanning]; 255 | 256 | if (_completionBlock) { 257 | _completionBlock(nil); 258 | } 259 | 260 | if (_delegate && [_delegate respondsToSelector:@selector(readerDidCancel:)]) { 261 | [_delegate readerDidCancel:self]; 262 | } 263 | } 264 | 265 | - (void)switchCameraAction:(UIButton *)button 266 | { 267 | [self switchDeviceInput]; 268 | } 269 | 270 | @end 271 | -------------------------------------------------------------------------------- /QRCodeReaderViewController/Resources/QRCodeBottomLeft@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhengjinghua/MQRCodeReaderViewController/6370cd1cd7b8f312df7d1b8ca912c05ff19498f1/QRCodeReaderViewController/Resources/QRCodeBottomLeft@2x.png -------------------------------------------------------------------------------- /QRCodeReaderViewController/Resources/QRCodeBottomLeft@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhengjinghua/MQRCodeReaderViewController/6370cd1cd7b8f312df7d1b8ca912c05ff19498f1/QRCodeReaderViewController/Resources/QRCodeBottomLeft@3x.png -------------------------------------------------------------------------------- /QRCodeReaderViewController/Resources/QRCodeBottomRight@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhengjinghua/MQRCodeReaderViewController/6370cd1cd7b8f312df7d1b8ca912c05ff19498f1/QRCodeReaderViewController/Resources/QRCodeBottomRight@2x.png -------------------------------------------------------------------------------- /QRCodeReaderViewController/Resources/QRCodeBottomRight@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhengjinghua/MQRCodeReaderViewController/6370cd1cd7b8f312df7d1b8ca912c05ff19498f1/QRCodeReaderViewController/Resources/QRCodeBottomRight@3x.png -------------------------------------------------------------------------------- /QRCodeReaderViewController/Resources/QRCodeLine@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhengjinghua/MQRCodeReaderViewController/6370cd1cd7b8f312df7d1b8ca912c05ff19498f1/QRCodeReaderViewController/Resources/QRCodeLine@2x.png -------------------------------------------------------------------------------- /QRCodeReaderViewController/Resources/QRCodeLine@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhengjinghua/MQRCodeReaderViewController/6370cd1cd7b8f312df7d1b8ca912c05ff19498f1/QRCodeReaderViewController/Resources/QRCodeLine@3x.png -------------------------------------------------------------------------------- /QRCodeReaderViewController/Resources/QRCodeTopLeft@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhengjinghua/MQRCodeReaderViewController/6370cd1cd7b8f312df7d1b8ca912c05ff19498f1/QRCodeReaderViewController/Resources/QRCodeTopLeft@2x.png -------------------------------------------------------------------------------- /QRCodeReaderViewController/Resources/QRCodeTopLeft@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhengjinghua/MQRCodeReaderViewController/6370cd1cd7b8f312df7d1b8ca912c05ff19498f1/QRCodeReaderViewController/Resources/QRCodeTopLeft@3x.png -------------------------------------------------------------------------------- /QRCodeReaderViewController/Resources/QRCodeTopRight@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhengjinghua/MQRCodeReaderViewController/6370cd1cd7b8f312df7d1b8ca912c05ff19498f1/QRCodeReaderViewController/Resources/QRCodeTopRight@2x.png -------------------------------------------------------------------------------- /QRCodeReaderViewController/Resources/QRCodeTopRight@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhengjinghua/MQRCodeReaderViewController/6370cd1cd7b8f312df7d1b8ca912c05ff19498f1/QRCodeReaderViewController/Resources/QRCodeTopRight@3x.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 |
3 |  创造不息,交付不止 4 |
5 | 6 | 7 | 8 |

9 | 10 | --- 11 | 12 | [English Guide](https://github.com/zhengjinghua/MQRCodeReaderViewController#readme-english) 13 | 14 | ## 说明 15 | 16 | MQRCodeReaderViewController 基于 [QRCodeReaderViewController](https://github.com/yannickl/QRCodeReaderViewController) 封装的二维码扫描控件, 仿照微信的二维码扫描器风格美化了界面, 直接加入你的项目中就能使用, 无需再次定制 UI. 17 | 18 | > Made with :heart: by [The EST Group](http://est-group.org) - We design and build: the Future! 19 | 20 | ![screenshot](http://7xnfdc.com1.z0.glb.clouddn.com/qrcode_screenshot.gif) 21 | 22 | ## 安装 23 | 24 | ### CocoaPods 安装 25 | 26 | 将下面代码复制进你的 `Podfile` 文件中 27 | 28 | ``` bash 29 | pod 'QRCodeReaderViewController', :git => 'https://github.com/zhengjinghua/MQRCodeReaderViewController.git' 30 | ``` 31 | 32 | ### 手工安装 33 | 34 | [下载](https://github.com/YannickL/QRCodeReaderViewController/archive/master.zip) 此项目, 然后将该项目里的 `QRCodeReaderViewController` 文件夹里的所有文件复制进你的项目中, 然后在需要调用此项目的地方引入 35 | 36 | ```objective-c 37 | #import "QRCodeReaderViewController.h" 38 | ``` 39 | 40 | ## 使用 41 | 42 | 支持以下两种方法调用, 选其一, 代码见下面: 43 | 44 | * 使用 Delegate 方法调用; 45 | * 使用 Block 方法调用; 46 | 47 | ```objective-c 48 | - (IBAction)scanAction:(id)sender 49 | { 50 | NSArray *types = @[AVMetadataObjectTypeQRCode]; 51 | _reader = [QRCodeReaderViewController readerWithMetadataObjectTypes:types]; 52 | 53 | // Using delegate methods 54 | _reader.delegate = self; 55 | 56 | // Or by using blocks 57 | [_reader setCompletionWithBlock:^(NSString *resultAsString) { 58 | [self dismissViewControllerAnimated:YES completion:^{ 59 | NSLog(@"%@", resultAsString); 60 | }]; 61 | }]; 62 | 63 | [self presentViewController:_reader animated:YES completion:NULL]; 64 | } 65 | 66 | #pragma mark - QRCodeReader Delegate Methods 67 | 68 | - (void)reader:(QRCodeReaderViewController *)reader didScanResult:(NSString *)result 69 | { 70 | [self dismissViewControllerAnimated:YES completion:^{ 71 | NSLog(@"%@", result); 72 | }]; 73 | } 74 | 75 | - (void)readerDidCancel:(QRCodeReaderViewController *)reader 76 | { 77 | [self dismissViewControllerAnimated:YES completion:NULL]; 78 | } 79 | ``` 80 | 81 | ## 协议 82 | 83 | MQRCodeReaderViewController 被许可在 MIT 协议下使用. 查阅 LICENSE 文件来获得更多信息. 84 | 85 | 86 | README (ENGLISH) 87 | ========== 88 | 89 | 90 | ## Description 91 | This projecd baesd on [QRCodeReaderViewController](https://github.com/yannickl/QRCodeReaderViewController), a little UI ajustment from `QRCodeReaderView`, make the interface more like **WeChat**. 92 | 93 | > Made with :heart: by [The EST Group](http://est-group.org) - We design and build: the Future! 94 | 95 | 96 | ## Install 97 | 98 | ### CocoaPods 99 | If you're using [CocoaPods](http://cocoapods.org/) (You are not?! You should!!) just add 100 | 101 | ``` bash 102 | pod 'QRCodeReaderViewController', :git => 'https://github.com/zhengjinghua/MQRCodeReaderViewController.git' 103 | ``` 104 | into your Podfile file. 105 | 106 | ### Manually 107 | 108 | [Download](https://github.com/zhengjinghua/MQRCodeReaderViewController/archive/master.zip) the project and copy the `QRCodeReaderViewController` folder into your project and then simply `#import "QRCodeReaderViewController.h"` in the file(s) you would like to use it in. 109 | 110 | ## Usage 111 | 112 | ```objective-c 113 | - (IBAction)scanAction:(id)sender 114 | { 115 | NSArray *types = @[AVMetadataObjectTypeQRCode]; 116 | _reader = [QRCodeReaderViewController readerWithMetadataObjectTypes:types]; 117 | 118 | // Using delegate methods 119 | _reader.delegate = self; 120 | 121 | // Or by using blocks 122 | [_reader setCompletionWithBlock:^(NSString *resultAsString) { 123 | [self dismissViewControllerAnimated:YES completion:^{ 124 | NSLog(@"%@", resultAsString); 125 | }]; 126 | }]; 127 | 128 | [self presentViewController:_reader animated:YES completion:NULL]; 129 | } 130 | 131 | #pragma mark - QRCodeReader Delegate Methods 132 | 133 | - (void)reader:(QRCodeReaderViewController *)reader didScanResult:(NSString *)result 134 | { 135 | [self dismissViewControllerAnimated:YES completion:^{ 136 | NSLog(@"%@", result); 137 | }]; 138 | } 139 | 140 | - (void)readerDidCancel:(QRCodeReaderViewController *)reader 141 | { 142 | [self dismissViewControllerAnimated:YES completion:NULL]; 143 | } 144 | ``` 145 | 146 | ## License 147 | 148 | StitchingImage is available under the MIT license. See the LICENSE file for more info. 149 | 150 | --- 151 | -------------------------------------------------------------------------------- /web/qrcodereaderviewcontroller_header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhengjinghua/MQRCodeReaderViewController/6370cd1cd7b8f312df7d1b8ca912c05ff19498f1/web/qrcodereaderviewcontroller_header.png -------------------------------------------------------------------------------- /web/screenshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhengjinghua/MQRCodeReaderViewController/6370cd1cd7b8f312df7d1b8ca912c05ff19498f1/web/screenshot.jpg --------------------------------------------------------------------------------