No Description

QRCodeScanView.swift 6.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. //
  2. // QRCodeScanView.swift
  3. // PaiAi
  4. //
  5. // Created by FFIB on 16/7/21.
  6. // Copyright © 2016年 FFIB. All rights reserved.
  7. //
  8. import UIKit
  9. import AVFoundation
  10. import CoreImage
  11. @IBDesignable public class QRCodeScanView: UIView {
  12. var qrmaskView: QRCodeMaskView?
  13. var qrscanner: QRCodeScanner?
  14. var indicatorView: UIActivityIndicatorView = {
  15. let indicator = UIActivityIndicatorView(style: .white)
  16. indicator.frame = CGRect(x: (UIScreen.main.bounds.width - 100) / 2 ,
  17. y: (UIScreen.main.bounds.height - 100) / 2,
  18. width: 100,
  19. height: 100)
  20. return indicator
  21. }()
  22. public var configuration = QRCodeConfiguration() {
  23. didSet {
  24. qrmaskView?.configuration = configuration
  25. }
  26. }
  27. public weak var delegate: QRCodeScanViewDelegate?
  28. let picker = UIImagePickerController()
  29. override public func layoutSubviews() {
  30. super.layoutSubviews()
  31. commonInit()
  32. }
  33. fileprivate func commonInit() {
  34. addSubview(indicatorView)
  35. indicatorView.startAnimating()
  36. setQRScanner()
  37. setMaskView()
  38. start()
  39. NotificationCenter.default.addObserver(self,
  40. selector: #selector(start),
  41. name: Notification.QRNotification.RestartNotification,
  42. object: nil)
  43. }
  44. fileprivate func setMaskView() {
  45. backgroundColor = UIColor.black
  46. qrmaskView = QRCodeMaskView(frame: CGRect(x: 0,
  47. y: 0,
  48. width: bounds.width,
  49. height: bounds.height))
  50. guard let view = qrmaskView else { return }
  51. view.configuration = configuration
  52. view.backgroundColor = UIColor(r: 0, g: 0, b: 0, a: 0.2)
  53. addSubview(view)
  54. }
  55. fileprivate func setQRScanner() {
  56. qrscanner = QRCodeScanner(scanRect: bounds)
  57. guard let qrscanner = qrscanner else { return }
  58. qrscanner.didDecodeCode = {[weak self] res in
  59. if let weakself = self {
  60. weakself.delegate?.scanView(weakself,
  61. receivedScanResult: res)
  62. weakself.qrmaskView?.stopAnimation()
  63. weakself.indicatorView.stopAnimating()
  64. }
  65. }
  66. qrscanner.didDecodeFail = {[weak self] error in
  67. if let weakself = self {
  68. weakself.delegate?.scanView(weakself,
  69. didFinshWithError: error)
  70. weakself.indicatorView.stopAnimating()
  71. }
  72. }
  73. guard let previewLayer = qrscanner.previewLayer else { return }
  74. previewLayer.frame = bounds
  75. layer.insertSublayer(previewLayer, at: 0)
  76. }
  77. @objc func start() {
  78. let queue = DispatchQueue(label: "FFIB.startScan.com")
  79. queue.async {
  80. self.qrscanner?.startScan()
  81. DispatchQueue.main.async {
  82. self.qrmaskView?.startAnimation()
  83. self.indicatorView.stopAnimating()
  84. }
  85. }
  86. }
  87. public func openLight() {
  88. guard let device = AVCaptureDevice.default(for: AVMediaType.video) else { return }
  89. do {
  90. try device.lockForConfiguration()
  91. if device.hasTorch && device.isTorchAvailable {
  92. if device.isTorchActive {
  93. device.torchMode = .off
  94. } else {
  95. device.torchMode = .on
  96. }
  97. }
  98. } catch {
  99. print("open light error")
  100. }
  101. }
  102. public func openPhotoLibrary(ctl: UIViewController) {
  103. indicatorView.startAnimating()
  104. let status = AVCaptureDevice.authorizationStatus(for: AVMediaType.video)
  105. if status == .notDetermined || status == .authorized {
  106. picker.sourceType = .photoLibrary
  107. picker.delegate = self
  108. ctl.present(picker, animated: true, completion: nil)
  109. } else {
  110. let alert = UIAlertController(title: "拒绝访问", message: "请在设置-隐私-相机中允许访问相册", preferredStyle: .alert)
  111. alert.addAction(UIAlertAction(title: "确定", style: .default, handler: nil))
  112. ctl.present(alert, animated: true, completion: nil)
  113. }
  114. }
  115. }
  116. extension QRCodeScanView: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
  117. public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
  118. picker.dismiss(animated: true) {
  119. guard let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage else { return }
  120. if let res = image.decodeQRCodeInImage() {
  121. self.qrscanner?.stopScan()
  122. self.qrmaskView?.stopAnimation()
  123. self.delegate?.scanView(self,
  124. receivedScanResult: QRCodeScanResult(metadataType: AVMetadataObject.ObjectType.qr.rawValue,
  125. result: res))
  126. } else {
  127. let error = NSError(domain: "decode qr code error",
  128. code: 101,
  129. userInfo: nil)
  130. self.delegate?.scanView(self,
  131. didFinshWithError: error)
  132. }
  133. self.indicatorView.stopAnimating()
  134. }
  135. }
  136. public func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
  137. picker.dismiss(animated: true, completion: nil)
  138. }
  139. }
  140. //qr code identify the pictures
  141. extension UIImage {
  142. /// 识别图片内的二维码
  143. ///
  144. /// - Returns: 二维码信息
  145. public func decodeQRCodeInImage() -> String? {
  146. guard let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: nil),
  147. let cgImage1 = self.cgImage else { return nil }
  148. let result = detector.features(in: CIImage(cgImage: cgImage1), options: [CIDetectorAccuracy: CIDetectorAccuracyHigh])
  149. guard let first = (result as? [CIQRCodeFeature])?.first else { return nil }
  150. return first.messageString
  151. }
  152. }