SWQRCodeViewController.m 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. //
  2. // SWQRCodeViewController.m
  3. // SWQRCode_Objc
  4. //
  5. // Created by zhuku on 2018/4/4.
  6. // Copyright © 2018年 selwyn. All rights reserved.
  7. //
  8. #import "SWQRCodeViewController.h"
  9. #import "SWScannerView.h"
  10. #import <Photos/Photos.h>
  11. @interface SWQRCodeViewController ()<AVCaptureMetadataOutputObjectsDelegate, AVCaptureVideoDataOutputSampleBufferDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate, TDNavigationBarDelegate>
  12. /** 扫描器 */
  13. @property (nonatomic, strong) SWScannerView *scannerView;
  14. @property (nonatomic, strong) AVCaptureSession *session;
  15. @end
  16. @implementation SWQRCodeViewController
  17. - (void)dealloc {
  18. [[NSNotificationCenter defaultCenter] removeObserver:self];
  19. }
  20. - (SWScannerView *)scannerView
  21. {
  22. if (!_scannerView) {
  23. _scannerView = [[SWScannerView alloc]initWithFrame:self.view.bounds config:_codeConfig];;
  24. }
  25. return _scannerView;
  26. }
  27. - (BOOL)hidesBottomBarWhenPushed{
  28. return YES;
  29. }
  30. - (void)viewDidLoad {
  31. [super viewDidLoad];
  32. [self loadStatusBarColor:[UIColor blackColor]];
  33. UIBarButtonItem *albumItem = [[UIBarButtonItem alloc]initWithTitle:@"相册" style:UIBarButtonItemStylePlain target:self action:@selector(showAlbum)];
  34. [albumItem setTintColor:[UIColor blackColor]];
  35. self.navigationItem.rightBarButtonItem = albumItem;
  36. self.navigationItem.title = [SWQRCodeManager sw_navigationItemTitleWithType:self.codeConfig.scannerType];
  37. [self _setupUI];
  38. [[NSNotificationCenter defaultCenter] addObserver:self
  39. selector:@selector(appDidBecomeActive:)
  40. name:UIApplicationDidBecomeActiveNotification
  41. object:nil];
  42. [[NSNotificationCenter defaultCenter] addObserver:self
  43. selector:@selector(appWillResignActive:)
  44. name:UIApplicationWillResignActiveNotification
  45. object:nil];
  46. self.fd_prefersNavigationBarHidden = YES;
  47. }
  48. - (void)viewWillAppear:(BOOL)animated
  49. {
  50. [super viewWillAppear:animated];
  51. [self resumeScanning];
  52. }
  53. - (void)viewWillDisappear:(BOOL)animated
  54. {
  55. [super viewWillDisappear:animated];
  56. [self.scannerView sw_setFlashlightOn:NO];
  57. [self.scannerView sw_hideFlashlightWithAnimated:YES];
  58. }
  59. - (void)_setupUI {
  60. [self.view addSubview:self.scannerView];
  61. self.view.backgroundColor = [UIColor colorWithWhite:0 alpha:.5f];
  62. TDNavigationBar *topBar = [[TDNavigationBar alloc] initNavigationBar];
  63. topBar.rightButton.hidden = NO;
  64. [topBar setNavigationTintType:NavigationTintTypeWhite];
  65. [topBar setBackButtonTitle:@" 信源"];
  66. [topBar.backButton setImageEdgeInsets:UIEdgeInsetsMake(0,20,0,0)];
  67. [topBar.backButton setTitleEdgeInsets:UIEdgeInsetsMake(0,0,0,-40)];
  68. topBar.backButton.frame = CGRectMake(0, 0,100,44);
  69. [topBar setRightButtonTitle:@"相册"];
  70. topBar.delegate = self;
  71. [self.view addSubview:topBar];
  72. // 校验相机权限
  73. [SWQRCodeManager sw_checkCameraAuthorizationStatusWithGrand:^(BOOL granted) {
  74. if (granted) {
  75. dispatch_async(dispatch_get_main_queue(), ^{
  76. [self _setupScanner];
  77. });
  78. }
  79. }];
  80. }
  81. #pragma mark - TDNavigationBarDelegate
  82. - (void)rightButtonAction:(TDButton *)sender {
  83. [self showAlbum];
  84. }
  85. /** 创建扫描器 */
  86. - (void)_setupScanner {
  87. AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
  88. AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
  89. AVCaptureMetadataOutput *metadataOutput = [[AVCaptureMetadataOutput alloc] init];
  90. [metadataOutput setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
  91. if (self.codeConfig.scannerArea == SWScannerAreaDefault) {
  92. 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);
  93. }
  94. AVCaptureVideoDataOutput *videoDataOutput = [[AVCaptureVideoDataOutput alloc] init];
  95. [videoDataOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
  96. self.session = [[AVCaptureSession alloc]init];
  97. [self.session setSessionPreset:AVCaptureSessionPresetHigh];
  98. if ([self.session canAddInput:deviceInput]) {
  99. [self.session addInput:deviceInput];
  100. }
  101. if ([self.session canAddOutput:metadataOutput]) {
  102. [self.session addOutput:metadataOutput];
  103. }
  104. if ([self.session canAddOutput:videoDataOutput]) {
  105. [self.session addOutput:videoDataOutput];
  106. }
  107. metadataOutput.metadataObjectTypes = [SWQRCodeManager sw_metadataObjectTypesWithType:self.codeConfig.scannerType];
  108. AVCaptureVideoPreviewLayer *videoPreviewLayer = [AVCaptureVideoPreviewLayer layerWithSession:_session];
  109. videoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
  110. videoPreviewLayer.frame = self.view.layer.bounds;
  111. [self.view.layer insertSublayer:videoPreviewLayer atIndex:0];
  112. [self.session startRunning];
  113. }
  114. #pragma mark -- 跳转相册
  115. - (void)imagePicker {
  116. UIImagePickerController *imagePicker = [[UIImagePickerController alloc]init];
  117. imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
  118. imagePicker.delegate = self;
  119. // [self presentViewController:imagePicker animated:YES completion:nil];
  120. imagePicker.navigationController.navigationBar.barTintColor = [UIColor redColor];
  121. [self presentViewController:imagePicker animated:YES completion:^{
  122. // UIViewController *control = imagePicker.viewControllers.lastObject;
  123. //
  124. //// UILabel *cancelLab=
  125. // control.view.superview.superview.superview.//((UILayoutContainerView *)0x10be2e610)
  126. // subviews.lastObject.//((UINavigationBar *)0x10be3bb90)
  127. // subviews.lastObject.//((_UINavigationBarContentView *)0x10bd19840)
  128. // subviews.firstObject.//((_UIButtonBarStackView *)0x10bd0fc30)
  129. // subviews.firstObject.//((_UIButtonBarButton *)0x10be68200)
  130. // subviews.firstObject.tintColor = [UIColor blackColor] ;//((_UIModernBarButton *)0x10bd99040)
  131. // control.view.superview.superview.superview.subviews.lastObject.subviews[2].subviews.firstObject.subviews.firstObject.subviews.firstObject.subviews.lastObject.opaque = YES;
  132. //// superview.superview.superview.superview.superview.tintColor = [UIColor blackColor];
  133. //// cancelLab.textColor = [UIColor blackColor];
  134. //
  135. //// UILabel *buttonLabel = control.navigationController.navigationBar.subviews.lastObject. //_UINavigationBarContentView
  136. //// subviews.firstObject.//_UIButtonBarStackView
  137. //// subviews.firstObject.//_UIButtonBarButton
  138. //// subviews.firstObject;//_UIModernBarButton
  139. ////
  140. ////// buttonLabel.textColor = [UIColor blueColor];
  141. //// UIButton * button = control.navigationController.navigationBar.subviews.lastObject. //_UINavigationBarContentView
  142. //// subviews.firstObject.//_UIButtonBarStackView
  143. //// subviews.firstObject;//_UIButtonBarButton
  144. ////// subviews.firstObject;//_UIModernBarButton
  145. ////
  146. //// //
  147. ////// UIBarButtonItem *rightBtn = [control valueForKey:@"imagePickerCancelButton"];
  148. ////// UIButton *tempButton = [rightBtn valueForKey:@"view"];
  149. //////// [tempButton setTitle:@"取消" forState:UIControlStateNormal];
  150. ////// [tempButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
  151. // imagePicker.navigationController.navigationBar.barTintColor = [UIColor blackColor];
  152. //
  153. }];
  154. imagePicker.modalTransitionStyle = self.navigationController.modalTransitionStyle;
  155. imagePicker.modalPresentationStyle = [UtilsTools modalPresentationStyle:self.navigationController.modalPresentationStyle];
  156. [self presentViewController:imagePicker animated:YES completion:nil];
  157. }
  158. #pragma mark -- AVCaptureMetadataOutputObjectsDelegate
  159. - (void)captureOutput:(AVCaptureOutput *)output didOutputMetadataObjects:(NSArray<__kindof AVMetadataObject *> *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
  160. // 获取扫一扫结果
  161. if (metadataObjects && metadataObjects.count > 0) {
  162. [self pauseScanning];
  163. AVMetadataMachineReadableCodeObject *metadataObject = metadataObjects[0];
  164. NSString *stringValue = metadataObject.stringValue;
  165. [self sw_handleWithValue:stringValue];
  166. }
  167. }
  168. #pragma mark -- AVCaptureVideoDataOutputSampleBufferDelegate
  169. /** 此方法会实时监听亮度值 */
  170. - (void)captureOutput:(AVCaptureOutput *)output didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
  171. CFDictionaryRef metadataDict = CMCopyDictionaryOfAttachments(NULL,sampleBuffer, kCMAttachmentMode_ShouldPropagate);
  172. NSDictionary *metadata = [[NSMutableDictionary alloc] initWithDictionary:(__bridge NSDictionary*)metadataDict];
  173. CFRelease(metadataDict);
  174. NSDictionary *exifMetadata = [[metadata objectForKey:(NSString *)kCGImagePropertyExifDictionary] mutableCopy];
  175. // 亮度值
  176. float brightnessValue = [[exifMetadata objectForKey:(NSString *)kCGImagePropertyExifBrightnessValue] floatValue];
  177. if (![self.scannerView sw_flashlightOn]) {
  178. if (brightnessValue < -4.0) {
  179. [self.scannerView sw_showFlashlightWithAnimated:YES];
  180. }else
  181. {
  182. [self.scannerView sw_hideFlashlightWithAnimated:YES];
  183. }
  184. }
  185. }
  186. - (void)showAlbum {
  187. // 校验相册权限
  188. [SWQRCodeManager sw_checkAlbumAuthorizationStatusWithGrand:^(BOOL granted) {
  189. if (granted) {
  190. [self imagePicker];
  191. }
  192. }];
  193. }
  194. #pragma mark -- UIImagePickerControllerDelegate
  195. - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
  196. {
  197. UIImage *pickImage = info[UIImagePickerControllerOriginalImage];
  198. CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{CIDetectorAccuracy: CIDetectorAccuracyHigh}];
  199. // 获取选择图片中识别结果
  200. NSArray *features = [detector featuresInImage:[CIImage imageWithData:UIImagePNGRepresentation(pickImage)]];
  201. [picker dismissViewControllerAnimated:YES completion:^{
  202. if (features.count > 0) {
  203. CIQRCodeFeature *feature = features[0];
  204. NSString *stringValue = feature.messageString;
  205. [self sw_handleWithValue:stringValue];
  206. }
  207. else {
  208. [self sw_didReadFromAlbumFailed];
  209. }
  210. }];
  211. }
  212. #pragma mark -- App 从后台进入前台
  213. - (void)appDidBecomeActive:(NSNotification *)notify {
  214. [self resumeScanning];
  215. }
  216. #pragma mark -- App 从前台进入后台
  217. - (void)appWillResignActive:(NSNotification *)notify {
  218. [self pauseScanning];
  219. }
  220. /** 恢复扫一扫功能 */
  221. - (void)resumeScanning {
  222. if (self.session) {
  223. [self.session startRunning];
  224. [self.scannerView sw_addScannerLineAnimation];
  225. }
  226. }
  227. /** 暂停扫一扫功能 */
  228. - (void)pauseScanning {
  229. if (self.session) {
  230. [self.session stopRunning];
  231. [self.scannerView sw_pauseScannerLineAnimation];
  232. }
  233. }
  234. #pragma mark -- 扫一扫API
  235. /**
  236. 处理扫一扫结果
  237. @param value 扫描结果
  238. */
  239. - (void)sw_handleWithValue:(NSString *)value {
  240. NSLog(@"sw_handleWithValue === %@", value);
  241. if ([self.delegate respondsToSelector:@selector(scanResult:)]) {
  242. [self.delegate scanResult:value];
  243. [self.navigationController popToRootViewControllerAnimated:YES];
  244. }
  245. // [[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://www.baidu.com?%@",value]] options:@{} completionHandler:^(BOOL success) {
  246. // [self.navigationController popToRootViewControllerAnimated:YES];
  247. // }];
  248. }
  249. /**
  250. 相册选取图片无法读取数据
  251. */
  252. - (void)sw_didReadFromAlbumFailed {
  253. NSLog(@"sw_didReadFromAlbumFailed");
  254. }
  255. - (void)didReceiveMemoryWarning {
  256. [super didReceiveMemoryWarning];
  257. // Dispose of any resources that can be recreated.
  258. }
  259. /*
  260. #pragma mark - Navigation
  261. // In a storyboard-based application, you will often want to do a little preparation before navigation
  262. - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
  263. // Get the new view controller using [segue destinationViewController].
  264. // Pass the selected object to the new view controller.
  265. }
  266. */
  267. @end