77//
88
99#import " ZXScanCodeViewController.h"
10- #import < AVFoundation/AVFoundation.h>
1110#import " ScanBGView.h"
11+ #import " Helper.h"
1212
13- @interface ZXScanCodeViewController ()<AVCaptureMetadataOutputObjectsDelegate>
13+ @interface ZXScanCodeViewController ()<AVCaptureMetadataOutputObjectsDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate >
1414@property (strong , nonatomic ) ScanBGView *myScanBGView;
1515@property (strong , nonatomic ) UIImageView *scanRectView, *lineView;
1616@property (strong , nonatomic ) UILabel *tipLabel;
1717
1818@property (strong , nonatomic ) AVCaptureVideoPreviewLayer *videoPreviewLayer;
19+ @property (strong , nonatomic ) CIDetector *detector;
1920@end
2021
2122@implementation ZXScanCodeViewController
2223
24+ - (CIDetector *)detector {
25+ if (!_detector) {
26+ _detector = [CIDetector detectorOfType: CIDetectorTypeQRCode context: nil options: @{ CIDetectorAccuracy : CIDetectorAccuracyHigh }];
27+ }
28+ return _detector;
29+ }
30+
2331- (void )viewDidLoad {
2432 [super viewDidLoad ];
2533
2634 self.title = @" 扫描二维码" ;
2735 self.view .backgroundColor = [UIColor blackColor ];
28-
36+ self.navigationItem .rightBarButtonItem = [UIBarButtonItem itemWithBtnTitle: @" 相册" target: self action: @selector (clickRightBarButton: )];
37+
2938 NSNotificationCenter *nc = [NSNotificationCenter defaultCenter ];
3039 [nc addObserver: self
3140 selector: @selector (applicationDidBecomeActive: )
@@ -35,19 +44,18 @@ - (void)viewDidLoad {
3544 selector: @selector (applicationWillResignActive: )
3645 name: UIApplicationWillResignActiveNotification
3746 object: nil ];
38-
3947}
4048
4149- (void )viewDidAppear : (BOOL )animated {
4250 [super viewDidAppear: animated];
43- [self configUI ];
51+ if (!_videoPreviewLayer) {
52+ [self configUI ];
53+ }
4454}
4555
4656- (void )viewWillDisappear : (BOOL )animated {
4757 [super viewWillDisappear: animated];
48- [self .videoPreviewLayer.session stopRunning ];
49- [self .videoPreviewLayer removeFromSuperlayer ];
50- [self scanLineStopAction ];
58+ [self stopScan ];
5159}
5260
5361- (void )configUI {
@@ -175,48 +183,79 @@ - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:
175183}
176184
177185- (void )analyseResult : (AVMetadataMachineReadableCodeObject *)result {
178- DebugLog ( @" result : %@ " , result.stringValue ) ;
179- if (result. stringValue .length <= 0 ) {
186+ NSString *resultStr = result.stringValue ;
187+ if (resultStr .length <= 0 ) {
180188 return ;
181189 }
182-
183190 // 停止扫描
184191 [self .videoPreviewLayer.session stopRunning ];
185192 [self scanLineStopAction ];
186-
187193 // 震动反馈
188194 AudioServicesPlaySystemSound (kSystemSoundID_Vibrate );
189-
190- // 解析结果
191- OTPAuthURL *authURL = [OTPAuthURL authURLWithURL: [NSURL URLWithString: result.stringValue] secret: nil ];
192- if ([authURL isKindOfClass: [TOTPAuthURL class ]]) {
193- if (self.sucessScanBlock ) {
194- self.sucessScanBlock (authURL);
195- }
196- [self .navigationController popViewControllerAnimated: YES ];
197- }else {
198- NSString *tipStr;
199- if (authURL) {
200- tipStr = @" 目前仅支持 TOTP 类型的身份验证令牌" ;
201- }else {
202- tipStr = [NSString stringWithFormat: @" 条码「%@ : %@ 」不是有效的身份验证令牌条码" , result.type, result.stringValue];
203- }
204- UIAlertView *alertV = [UIAlertView bk_alertViewWithTitle: @" 无效条码" message: tipStr];
205- [alertV bk_addButtonWithTitle: @" 重试" handler: ^{
206- [self .videoPreviewLayer.session startRunning ];
207- [self scanLineStartAction ];
208- }];
209- [alertV show ];
195+ // 交给 block 处理
196+ if (_scanResultBlock) {
197+ _scanResultBlock (self, resultStr);
210198 }
211199}
212200
213201#pragma mark Notification
214202- (void )applicationDidBecomeActive : (UIApplication *)application {
215- [self .videoPreviewLayer.session startRunning ];
216- [self scanLineStartAction ];
203+ [self startScan ];
217204}
218205
219206- (void )applicationWillResignActive : (UIApplication *)application {
207+ [self stopScan ];
208+ }
209+ #pragma mark Photo
210+ -(void )clickRightBarButton : (UIBarButtonItem*)item {
211+ if (![Helper checkPhotoLibraryAuthorizationStatus ]) {
212+ return ;
213+ }
214+ // 停止扫描
215+ [self .videoPreviewLayer.session stopRunning ];
216+ [self scanLineStopAction ];
217+
218+ UIImagePickerController *picker = [UIImagePickerController new ];
219+ picker.delegate = self;
220+ picker.allowsEditing = NO ;
221+ picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
222+ [self .navigationController presentViewController: picker animated: YES completion: nil ];
223+ }
224+
225+ - (void )imagePickerController : (UIImagePickerController *)picker didFinishPickingMediaWithInfo : (NSDictionary <NSString *,id> *)info {
226+ [picker dismissViewControllerAnimated: YES completion: nil ];
227+ UIImage *image = [info objectForKey: UIImagePickerControllerEditedImage];
228+ if (!image){
229+ image = [info objectForKey: UIImagePickerControllerOriginalImage];
230+ }
231+ __block NSString *resultStr = nil ;
232+ NSArray *features = [self .detector featuresInImage: [CIImage imageWithCGImage: image.CGImage]];
233+ [features enumerateObjectsUsingBlock: ^(CIQRCodeFeature *obj, NSUInteger idx, BOOL *stop) {
234+ if (obj.messageString .length > 0 ) {
235+ resultStr = obj.messageString ;
236+ *stop = YES ;
237+ }
238+ }];
239+ // 震动反馈
240+ AudioServicesPlaySystemSound (kSystemSoundID_Vibrate );
241+ // 交给 block 处理
242+ if (_scanResultBlock) {
243+ _scanResultBlock (self, resultStr);
244+ }
245+ }
246+ - (void )imagePickerControllerDidCancel : (UIImagePickerController *)picker {
247+ [picker dismissViewControllerAnimated: YES completion: nil ];
248+ }
249+
250+ #pragma mark public
251+ - (BOOL )isScaning {
252+ return _videoPreviewLayer.session .isRunning ;
253+ }
254+ - (void )startScan {
255+ [self .videoPreviewLayer.session startRunning ];
256+ [self scanLineStartAction ];
257+ }
258+ - (void )stopScan {
220259 [self .videoPreviewLayer.session stopRunning ];
221260 [self scanLineStopAction ];
222261}
0 commit comments