Skip to content

Commit 094b28c

Browse files
committed
二维码扫描改用原生库
1 parent 87b426f commit 094b28c

2 files changed

Lines changed: 81 additions & 88 deletions

File tree

Coding_iOS.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@
395395
4ED673221A8E0ECC00DF2D1A /* SVWebViewControllerActivityReport.m in Sources */ = {isa = PBXBuildFile; fileRef = 4ED673211A8E0ECC00DF2D1A /* SVWebViewControllerActivityReport.m */; };
396396
4ED673261A8E127100DF2D1A /* SVWebViewControllerActivityReport@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4ED673251A8E127100DF2D1A /* SVWebViewControllerActivityReport@2x.png */; };
397397
4ED673281A8E12F900DF2D1A /* SVWebViewControllerActivityReport-iPad@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4ED673271A8E12F900DF2D1A /* SVWebViewControllerActivityReport-iPad@2x.png */; };
398+
4EDBECEB1B709EB3003E87C3 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4EDBECEA1B709EB3003E87C3 /* AVFoundation.framework */; };
398399
4EDC33CE1AFB4DCC00698315 /* EaseInputTipsView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EDC33CD1AFB4DCC00698315 /* EaseInputTipsView.m */; };
399400
4EDD8F511A36F42200E9E232 /* libXG-SDK.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4EDD8F4D1A36F42200E9E232 /* libXG-SDK.a */; };
400401
4EDD8F521A36F42300E9E232 /* ReleaseNotes.txt in Resources */ = {isa = PBXBuildFile; fileRef = 4EDD8F4E1A36F42200E9E232 /* ReleaseNotes.txt */; };
@@ -1398,6 +1399,7 @@
13981399
4ED673211A8E0ECC00DF2D1A /* SVWebViewControllerActivityReport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SVWebViewControllerActivityReport.m; sourceTree = "<group>"; };
13991400
4ED673251A8E127100DF2D1A /* SVWebViewControllerActivityReport@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "SVWebViewControllerActivityReport@2x.png"; sourceTree = "<group>"; };
14001401
4ED673271A8E12F900DF2D1A /* SVWebViewControllerActivityReport-iPad@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "SVWebViewControllerActivityReport-iPad@2x.png"; sourceTree = "<group>"; };
1402+
4EDBECEA1B709EB3003E87C3 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
14011403
4EDC33CC1AFB4DCC00698315 /* EaseInputTipsView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EaseInputTipsView.h; sourceTree = "<group>"; };
14021404
4EDC33CD1AFB4DCC00698315 /* EaseInputTipsView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EaseInputTipsView.m; sourceTree = "<group>"; };
14031405
4EDD8F4D1A36F42200E9E232 /* libXG-SDK.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libXG-SDK.a"; sourceTree = "<group>"; };
@@ -1972,6 +1974,7 @@
19721974
isa = PBXFrameworksBuildPhase;
19731975
buildActionMask = 2147483647;
19741976
files = (
1977+
4EDBECEB1B709EB3003E87C3 /* AVFoundation.framework in Frameworks */,
19751978
0AB591AD1AB6D51C0076C454 /* MapKit.framework in Frameworks */,
19761979
0A6E6BBF1AB180CB004C0107 /* CoreLocation.framework in Frameworks */,
19771980
4EDD8F5C1A36F52700E9E232 /* libsqlite3.0.dylib in Frameworks */,
@@ -2903,6 +2906,7 @@
29032906
8E477012198770E700997D05 /* Frameworks */ = {
29042907
isa = PBXGroup;
29052908
children = (
2909+
4EDBECEA1B709EB3003E87C3 /* AVFoundation.framework */,
29062910
4EF818231B09D8D8005F974B /* WebP.framework */,
29072911
0A6E6BBE1AB180CB004C0107 /* CoreLocation.framework */,
29082912
0A6E6BBC1AB180AE004C0107 /* MapKit.framework */,

Coding_iOS/Ease_2FA/Controllers/ZXScanCodeViewController.m

Lines changed: 77 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@
77
//
88

99
#import "ZXScanCodeViewController.h"
10+
#import <AVFoundation/AVFoundation.h>
1011
#import "ScanBGView.h"
11-
#import <ZXingObjC/ZXingObjC.h>
1212

13-
@interface ZXScanCodeViewController ()<ZXCaptureDelegate>
14-
@property (nonatomic, strong) ZXCapture *capture;
13+
@interface ZXScanCodeViewController ()<AVCaptureMetadataOutputObjectsDelegate>
1514
@property (strong, nonatomic) ScanBGView *myScanBGView;
1615
@property (strong, nonatomic) UIImageView *scanRectView, *lineView;
1716
@property (strong, nonatomic) UILabel *tipLabel;
18-
@property (assign, nonatomic) BOOL scanSucessed;
17+
18+
@property (strong, nonatomic) AVCaptureVideoPreviewLayer *videoPreviewLayer;
1919
@end
2020

2121
@implementation ZXScanCodeViewController
@@ -45,8 +45,8 @@ - (void)viewDidAppear:(BOOL)animated {
4545

4646
- (void)viewWillDisappear:(BOOL)animated{
4747
[super viewWillDisappear:animated];
48-
[self.capture stop];
49-
[self.capture.layer removeFromSuperlayer];
48+
[self.videoPreviewLayer.session stopRunning];
49+
[self.videoPreviewLayer removeFromSuperlayer];
5050
[self scanLineStopAction];
5151
}
5252

@@ -55,14 +55,38 @@ - (void)configUI{
5555
CGFloat padding = (kScreen_Width - width)/2;
5656
CGRect scanRect = CGRectMake(padding, kScreen_Height/10, width, width);
5757

58-
if (!_capture) {
59-
_capture = [[ZXCapture alloc] init];
60-
_capture.camera = _capture.back;
61-
_capture.focusMode = AVCaptureFocusModeContinuousAutoFocus;
62-
_capture.rotation = 90.f;
63-
_capture.layer.frame = self.view.bounds;
64-
_capture.scanRect = scanRect;
65-
_capture.delegate = self;
58+
if (!_videoPreviewLayer) {
59+
NSError *error;
60+
AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
61+
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];
62+
if (!input) {
63+
kTipAlert(@"%@", error.localizedDescription);
64+
[self.navigationController popViewControllerAnimated:YES];
65+
}else{
66+
//设置会话的输入设备
67+
AVCaptureSession *captureSession = [AVCaptureSession new];
68+
[captureSession addInput:input];
69+
//对应输出
70+
AVCaptureMetadataOutput *captureMetadataOutput = [[AVCaptureMetadataOutput alloc] init];
71+
[captureMetadataOutput setMetadataObjectsDelegate:self queue:dispatch_queue_create("ease_capture_queue",NULL)];
72+
[captureSession addOutput:captureMetadataOutput];
73+
74+
//设置条码类型:包含 AVMetadataObjectTypeQRCode 就好
75+
if (![captureMetadataOutput.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeQRCode]) {
76+
kTipAlert(@"摄像头不支持扫描二维码!");
77+
[self.navigationController popViewControllerAnimated:YES];
78+
}else{
79+
[captureMetadataOutput setMetadataObjectTypes:captureMetadataOutput.availableMetadataObjectTypes];
80+
}
81+
captureMetadataOutput.rectOfInterest = CGRectMake(CGRectGetMinY(scanRect)/CGRectGetHeight(self.view.frame),
82+
1 - CGRectGetMaxX(scanRect)/CGRectGetWidth(self.view.frame),
83+
CGRectGetHeight(scanRect)/CGRectGetHeight(self.view.frame),
84+
CGRectGetWidth(scanRect)/CGRectGetWidth(self.view.frame));//设置扫描区域。。默认是手机头向左的横屏坐标系(逆时针旋转90度)
85+
//将捕获的数据流展现出来
86+
_videoPreviewLayer = [AVCaptureVideoPreviewLayer layerWithSession:captureSession];
87+
[_videoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
88+
[_videoPreviewLayer setFrame:self.view.bounds];
89+
}
6690
}
6791

6892
if (!_myScanBGView) {
@@ -92,7 +116,7 @@ - (void)configUI{
92116
_lineView.image = lineImage;
93117
}
94118

95-
[self.view.layer addSublayer:_capture.layer];
119+
[self.view.layer addSublayer:_videoPreviewLayer];
96120
[self.view addSubview:_myScanBGView];
97121
[self.view addSubview:_scanRectView];
98122
[self.view addSubview:_tipLabel];
@@ -101,8 +125,8 @@ - (void)configUI{
101125
make.top.equalTo(_scanRectView.mas_bottom).offset(20);
102126
make.height.mas_equalTo(30);
103127
}];
104-
[_capture start];
105128
[_scanRectView addSubview:_lineView];
129+
[_videoPreviewLayer.session startRunning];
106130
[self scanLineStartAction];
107131
}
108132

@@ -123,80 +147,48 @@ - (void)scanLineStopAction{
123147
}
124148

125149
- (void)dealloc {
126-
[self.capture.layer removeFromSuperlayer];
127-
self.capture = nil;
150+
[self.videoPreviewLayer removeFromSuperlayer];
151+
self.videoPreviewLayer = nil;
128152
[self scanLineStopAction];
129153
[[NSNotificationCenter defaultCenter] removeObserver:self];
130154
}
131155

132-
#pragma p_Method
133-
- (NSString *)barcodeFormatToString:(ZXBarcodeFormat)format {
134-
switch (format) {
135-
case kBarcodeFormatAztec:
136-
return @"Aztec";
137-
138-
case kBarcodeFormatCodabar:
139-
return @"CODABAR";
140-
141-
case kBarcodeFormatCode39:
142-
return @"Code 39";
143-
144-
case kBarcodeFormatCode93:
145-
return @"Code 93";
146-
147-
case kBarcodeFormatCode128:
148-
return @"Code 128";
149-
150-
case kBarcodeFormatDataMatrix:
151-
return @"Data Matrix";
152-
153-
case kBarcodeFormatEan8:
154-
return @"EAN-8";
155-
156-
case kBarcodeFormatEan13:
157-
return @"EAN-13";
158-
159-
case kBarcodeFormatITF:
160-
return @"ITF";
161-
162-
case kBarcodeFormatPDF417:
163-
return @"PDF417";
164-
165-
case kBarcodeFormatQRCode:
166-
return @"QR Code";
167-
168-
case kBarcodeFormatRSS14:
169-
return @"RSS 14";
170-
171-
case kBarcodeFormatRSSExpanded:
172-
return @"RSS Expanded";
173-
174-
case kBarcodeFormatUPCA:
175-
return @"UPCA";
176-
177-
case kBarcodeFormatUPCE:
178-
return @"UPCE";
179-
180-
case kBarcodeFormatUPCEANExtension:
181-
return @"UPC/EAN extension";
182-
183-
default:
184-
return @"Unknown";
156+
#pragma mark AVCaptureMetadataOutputObjectsDelegate
157+
158+
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{
159+
//判断是否有数据,是否是二维码数据
160+
if (metadataObjects.count > 0) {
161+
__block AVMetadataMachineReadableCodeObject *result = nil;
162+
[metadataObjects enumerateObjectsUsingBlock:^(AVMetadataMachineReadableCodeObject *obj, NSUInteger idx, BOOL *stop) {
163+
if ([obj.type isEqualToString:AVMetadataObjectTypeQRCode]) {
164+
result = obj;
165+
*stop = YES;
166+
}
167+
}];
168+
if (!result) {
169+
result = [metadataObjects firstObject];
170+
}
171+
dispatch_async(dispatch_get_main_queue(), ^{
172+
[self analyseResult:result];
173+
});
185174
}
186175
}
187176

188-
#pragma mark ZXCaptureDelegate
189-
- (void)captureResult:(ZXCapture *)capture result:(ZXResult *)result{
190-
NSLog(@"result : %@", result.text);
191-
192-
if (!result || _scanSucessed) return;
193-
_scanSucessed = YES;
194-
[capture stop];
177+
- (void)analyseResult:(AVMetadataMachineReadableCodeObject *)result{
178+
DebugLog(@"result : %@", result.stringValue);
179+
if (result.stringValue.length <= 0) {
180+
return;
181+
}
195182

196-
// Vibrate
183+
//停止扫描
184+
[self.videoPreviewLayer.session stopRunning];
185+
[self scanLineStopAction];
186+
187+
//震动反馈
197188
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
198189

199-
OTPAuthURL *authURL = [OTPAuthURL authURLWithURL:[NSURL URLWithString:result.text] secret:nil];
190+
//解析结果
191+
OTPAuthURL *authURL = [OTPAuthURL authURLWithURL:[NSURL URLWithString:result.stringValue] secret:nil];
200192
if ([authURL isKindOfClass:[TOTPAuthURL class]]) {
201193
if (self.sucessScanBlock) {
202194
self.sucessScanBlock(authURL);
@@ -207,28 +199,25 @@ - (void)captureResult:(ZXCapture *)capture result:(ZXResult *)result{
207199
if (authURL) {
208200
tipStr = @"目前仅支持 TOTP 类型的身份验证令牌";
209201
}else{
210-
NSString *formatString = [self barcodeFormatToString:result.barcodeFormat];
211-
NSString *resultString = result.text;
212-
tipStr = [NSString stringWithFormat:@"条码「%@ : %@」不是有效的身份验证令牌条码", formatString, resultString];
202+
tipStr = [NSString stringWithFormat:@"条码「%@ : %@」不是有效的身份验证令牌条码", result.type, result.stringValue];
213203
}
214-
215204
UIAlertView *alertV = [UIAlertView bk_alertViewWithTitle:@"无效条码" message:tipStr];
216205
[alertV bk_addButtonWithTitle:@"重试" handler:^{
217-
self.scanSucessed = NO;
218-
[capture start];
206+
[self.videoPreviewLayer.session startRunning];
207+
[self scanLineStartAction];
219208
}];
220209
[alertV show];
221210
}
222211
}
223212

224213
#pragma mark Notification
225214
- (void)applicationDidBecomeActive:(UIApplication *)application {
226-
[self.capture start];
215+
[self.videoPreviewLayer.session startRunning];
227216
[self scanLineStartAction];
228217
}
229218

230219
- (void)applicationWillResignActive:(UIApplication *)application {
231-
[self.capture stop];
220+
[self.videoPreviewLayer.session stopRunning];
232221
[self scanLineStopAction];
233222
}
234223
@end

0 commit comments

Comments
 (0)