No Description

QRCodeScanView.swift 6.3KB

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