// // SWQRCodeViewController.m // SWQRCode_Objc // // Created by zhuku on 2018/4/4. // Copyright © 2018年 selwyn. All rights reserved. // #import "SWQRCodeViewController.h" #import "SWScannerView.h" #import @interface SWQRCodeViewController () /** 扫描器 */ @property (nonatomic, strong) SWScannerView *scannerView; @property (nonatomic, strong) AVCaptureSession *session; @end @implementation SWQRCodeViewController - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (SWScannerView *)scannerView { if (!_scannerView) { _scannerView = [[SWScannerView alloc]initWithFrame:self.view.bounds config:_codeConfig];; } return _scannerView; } - (BOOL)hidesBottomBarWhenPushed{ return YES; } - (void)viewDidLoad { [super viewDidLoad]; [self loadStatusBarColor:[UIColor blackColor]]; UIBarButtonItem *albumItem = [[UIBarButtonItem alloc]initWithTitle:@"相册" style:UIBarButtonItemStylePlain target:self action:@selector(showAlbum)]; [albumItem setTintColor:[UIColor blackColor]]; self.navigationItem.rightBarButtonItem = albumItem; self.navigationItem.title = [SWQRCodeManager sw_navigationItemTitleWithType:self.codeConfig.scannerType]; [self _setupUI]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appWillResignActive:) name:UIApplicationWillResignActiveNotification object:nil]; self.fd_prefersNavigationBarHidden = YES; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self resumeScanning]; } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; [self.scannerView sw_setFlashlightOn:NO]; [self.scannerView sw_hideFlashlightWithAnimated:YES]; } - (void)_setupUI { [self.view addSubview:self.scannerView]; self.view.backgroundColor = [UIColor colorWithWhite:0 alpha:.5f]; TDNavigationBar *topBar = [[TDNavigationBar alloc] initNavigationBar]; topBar.rightButton.hidden = NO; [topBar setNavigationTintType:NavigationTintTypeWhite]; [topBar setBackButtonTitle:@" 信源"]; [topBar.backButton setImageEdgeInsets:UIEdgeInsetsMake(0,20,0,0)]; [topBar.backButton setTitleEdgeInsets:UIEdgeInsetsMake(0,0,0,-40)]; topBar.backButton.frame = CGRectMake(0, 0,100,44); [topBar setRightButtonTitle:@"相册"]; topBar.delegate = self; [self.view addSubview:topBar]; // 校验相机权限 [SWQRCodeManager sw_checkCameraAuthorizationStatusWithGrand:^(BOOL granted) { if (granted) { dispatch_async(dispatch_get_main_queue(), ^{ [self _setupScanner]; }); } }]; } #pragma mark - TDNavigationBarDelegate - (void)rightButtonAction:(TDButton *)sender { [self showAlbum]; } /** 创建扫描器 */ - (void)_setupScanner { AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil]; AVCaptureMetadataOutput *metadataOutput = [[AVCaptureMetadataOutput alloc] init]; [metadataOutput setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()]; if (self.codeConfig.scannerArea == SWScannerAreaDefault) { metadataOutput.rectOfInterest = CGRectMake([self.scannerView scanner_y]/self.view.frame.size.height, [self.scannerView scanner_x]/self.view.frame.size.width, [self.scannerView scanner_width]/self.view.frame.size.height, [self.scannerView scanner_width]/self.view.frame.size.width); } AVCaptureVideoDataOutput *videoDataOutput = [[AVCaptureVideoDataOutput alloc] init]; [videoDataOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()]; self.session = [[AVCaptureSession alloc]init]; [self.session setSessionPreset:AVCaptureSessionPresetHigh]; if ([self.session canAddInput:deviceInput]) { [self.session addInput:deviceInput]; } if ([self.session canAddOutput:metadataOutput]) { [self.session addOutput:metadataOutput]; } if ([self.session canAddOutput:videoDataOutput]) { [self.session addOutput:videoDataOutput]; } metadataOutput.metadataObjectTypes = [SWQRCodeManager sw_metadataObjectTypesWithType:self.codeConfig.scannerType]; AVCaptureVideoPreviewLayer *videoPreviewLayer = [AVCaptureVideoPreviewLayer layerWithSession:_session]; videoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; videoPreviewLayer.frame = self.view.layer.bounds; [self.view.layer insertSublayer:videoPreviewLayer atIndex:0]; [self.session startRunning]; } #pragma mark -- 跳转相册 - (void)imagePicker { UIImagePickerController *imagePicker = [[UIImagePickerController alloc]init]; imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; imagePicker.delegate = self; // [self presentViewController:imagePicker animated:YES completion:nil]; imagePicker.navigationController.navigationBar.barTintColor = [UIColor redColor]; [self presentViewController:imagePicker animated:YES completion:^{ // UIViewController *control = imagePicker.viewControllers.lastObject; // //// UILabel *cancelLab= // control.view.superview.superview.superview.//((UILayoutContainerView *)0x10be2e610) // subviews.lastObject.//((UINavigationBar *)0x10be3bb90) // subviews.lastObject.//((_UINavigationBarContentView *)0x10bd19840) // subviews.firstObject.//((_UIButtonBarStackView *)0x10bd0fc30) // subviews.firstObject.//((_UIButtonBarButton *)0x10be68200) // subviews.firstObject.tintColor = [UIColor blackColor] ;//((_UIModernBarButton *)0x10bd99040) // control.view.superview.superview.superview.subviews.lastObject.subviews[2].subviews.firstObject.subviews.firstObject.subviews.firstObject.subviews.lastObject.opaque = YES; //// superview.superview.superview.superview.superview.tintColor = [UIColor blackColor]; //// cancelLab.textColor = [UIColor blackColor]; // //// UILabel *buttonLabel = control.navigationController.navigationBar.subviews.lastObject. //_UINavigationBarContentView //// subviews.firstObject.//_UIButtonBarStackView //// subviews.firstObject.//_UIButtonBarButton //// subviews.firstObject;//_UIModernBarButton //// ////// buttonLabel.textColor = [UIColor blueColor]; //// UIButton * button = control.navigationController.navigationBar.subviews.lastObject. //_UINavigationBarContentView //// subviews.firstObject.//_UIButtonBarStackView //// subviews.firstObject;//_UIButtonBarButton ////// subviews.firstObject;//_UIModernBarButton //// //// // ////// UIBarButtonItem *rightBtn = [control valueForKey:@"imagePickerCancelButton"]; ////// UIButton *tempButton = [rightBtn valueForKey:@"view"]; //////// [tempButton setTitle:@"取消" forState:UIControlStateNormal]; ////// [tempButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; // imagePicker.navigationController.navigationBar.barTintColor = [UIColor blackColor]; // }]; imagePicker.modalTransitionStyle = self.navigationController.modalTransitionStyle; imagePicker.modalPresentationStyle = [UtilsTools modalPresentationStyle:self.navigationController.modalPresentationStyle]; [self presentViewController:imagePicker animated:YES completion:nil]; } #pragma mark -- AVCaptureMetadataOutputObjectsDelegate - (void)captureOutput:(AVCaptureOutput *)output didOutputMetadataObjects:(NSArray<__kindof AVMetadataObject *> *)metadataObjects fromConnection:(AVCaptureConnection *)connection { // 获取扫一扫结果 if (metadataObjects && metadataObjects.count > 0) { [self pauseScanning]; AVMetadataMachineReadableCodeObject *metadataObject = metadataObjects[0]; NSString *stringValue = metadataObject.stringValue; [self sw_handleWithValue:stringValue]; } } #pragma mark -- AVCaptureVideoDataOutputSampleBufferDelegate /** 此方法会实时监听亮度值 */ - (void)captureOutput:(AVCaptureOutput *)output didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection { CFDictionaryRef metadataDict = CMCopyDictionaryOfAttachments(NULL,sampleBuffer, kCMAttachmentMode_ShouldPropagate); NSDictionary *metadata = [[NSMutableDictionary alloc] initWithDictionary:(__bridge NSDictionary*)metadataDict]; CFRelease(metadataDict); NSDictionary *exifMetadata = [[metadata objectForKey:(NSString *)kCGImagePropertyExifDictionary] mutableCopy]; // 亮度值 float brightnessValue = [[exifMetadata objectForKey:(NSString *)kCGImagePropertyExifBrightnessValue] floatValue]; if (![self.scannerView sw_flashlightOn]) { if (brightnessValue < -4.0) { [self.scannerView sw_showFlashlightWithAnimated:YES]; }else { [self.scannerView sw_hideFlashlightWithAnimated:YES]; } } } - (void)showAlbum { // 校验相册权限 [SWQRCodeManager sw_checkAlbumAuthorizationStatusWithGrand:^(BOOL granted) { if (granted) { [self imagePicker]; } }]; } #pragma mark -- UIImagePickerControllerDelegate - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { UIImage *pickImage = info[UIImagePickerControllerOriginalImage]; CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{CIDetectorAccuracy: CIDetectorAccuracyHigh}]; // 获取选择图片中识别结果 NSArray *features = [detector featuresInImage:[CIImage imageWithData:UIImagePNGRepresentation(pickImage)]]; [picker dismissViewControllerAnimated:YES completion:^{ if (features.count > 0) { CIQRCodeFeature *feature = features[0]; NSString *stringValue = feature.messageString; [self sw_handleWithValue:stringValue]; } else { [self sw_didReadFromAlbumFailed]; } }]; } #pragma mark -- App 从后台进入前台 - (void)appDidBecomeActive:(NSNotification *)notify { [self resumeScanning]; } #pragma mark -- App 从前台进入后台 - (void)appWillResignActive:(NSNotification *)notify { [self pauseScanning]; } /** 恢复扫一扫功能 */ - (void)resumeScanning { if (self.session) { [self.session startRunning]; [self.scannerView sw_addScannerLineAnimation]; } } /** 暂停扫一扫功能 */ - (void)pauseScanning { if (self.session) { [self.session stopRunning]; [self.scannerView sw_pauseScannerLineAnimation]; } } #pragma mark -- 扫一扫API /** 处理扫一扫结果 @param value 扫描结果 */ - (void)sw_handleWithValue:(NSString *)value { NSLog(@"sw_handleWithValue === %@", value); if ([self.delegate respondsToSelector:@selector(scanResult:)]) { [self.delegate scanResult:value]; [self.navigationController popToRootViewControllerAnimated:YES]; } // [[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://www.baidu.com?%@",value]] options:@{} completionHandler:^(BOOL success) { // [self.navigationController popToRootViewControllerAnimated:YES]; // }]; } /** 相册选取图片无法读取数据 */ - (void)sw_didReadFromAlbumFailed { NSLog(@"sw_didReadFromAlbumFailed"); } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } /* #pragma mark - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // Get the new view controller using [segue destinationViewController]. // Pass the selected object to the new view controller. } */ @end