123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- import UIKit
- import AVFoundation
- import CoreImage
- @IBDesignable public class QRCodeScanView: UIView {
- var qrmaskView: QRCodeMaskView?
- var qrscanner: QRCodeScanner?
- var indicatorView: UIActivityIndicatorView = {
- let indicator = UIActivityIndicatorView(style: .white)
- indicator.frame = CGRect(x: (UIScreen.main.bounds.width - 100) / 2 ,
- y: (UIScreen.main.bounds.height - 100) / 2,
- width: 100,
- height: 100)
- return indicator
- }()
- public var configuration = QRCodeConfiguration() {
- didSet {
- qrmaskView?.configuration = configuration
- }
- }
- public weak var delegate: QRCodeScanViewDelegate?
- let picker = UIImagePickerController()
- override public func layoutSubviews() {
- super.layoutSubviews()
- commonInit()
- }
- fileprivate func commonInit() {
- addSubview(indicatorView)
- indicatorView.startAnimating()
- setQRScanner()
- setMaskView()
- start()
- NotificationCenter.default.addObserver(self,
- selector: #selector(start),
- name: Notification.QRNotification.RestartNotification,
- object: nil)
- }
- fileprivate func setMaskView() {
- backgroundColor = UIColor.black
- qrmaskView = QRCodeMaskView(frame: CGRect(x: 0,
- y: 0,
- width: bounds.width,
- height: bounds.height))
- guard let view = qrmaskView else { return }
- view.configuration = configuration
- view.backgroundColor = UIColor(r: 0, g: 0, b: 0, a: 0.2)
- addSubview(view)
- }
- fileprivate func setQRScanner() {
- qrscanner = QRCodeScanner(scanRect: bounds)
- guard let qrscanner = qrscanner else { return }
- qrscanner.didDecodeCode = {[weak self] res in
- if let weakself = self {
- weakself.delegate?.scanView(weakself,
- receivedScanResult: res)
- weakself.qrmaskView?.stopAnimation()
- weakself.indicatorView.stopAnimating()
- }
- }
- qrscanner.didDecodeFail = {[weak self] error in
- if let weakself = self {
- weakself.delegate?.scanView(weakself,
- didFinshWithError: error)
- weakself.indicatorView.stopAnimating()
- }
- }
- guard let previewLayer = qrscanner.previewLayer else { return }
- previewLayer.frame = bounds
- layer.insertSublayer(previewLayer, at: 0)
- }
- @objc func start() {
- let queue = DispatchQueue(label: "FFIB.startScan.com")
- queue.async {
- self.qrscanner?.startScan()
- DispatchQueue.main.async {
- self.qrmaskView?.startAnimation()
- self.indicatorView.stopAnimating()
- }
- }
- }
- public func openLight() {
- guard let device = AVCaptureDevice.default(for: AVMediaType.video) else { return }
- do {
- try device.lockForConfiguration()
- if device.hasTorch && device.isTorchAvailable {
- if device.isTorchActive {
- device.torchMode = .off
- } else {
- device.torchMode = .on
- }
- }
- } catch {
- print("open light error")
- }
- }
- public func openPhotoLibrary(ctl: UIViewController) {
- indicatorView.startAnimating()
- let status = AVCaptureDevice.authorizationStatus(for: AVMediaType.video)
- if status == .notDetermined || status == .authorized {
- picker.sourceType = .photoLibrary
- picker.delegate = self
- ctl.present(picker, animated: true, completion: nil)
- } else {
- let alert = UIAlertController(title: "拒绝访问", message: "请在设置-隐私-相机中允许访问相册", preferredStyle: .alert)
- alert.addAction(UIAlertAction(title: "确定", style: .default, handler: nil))
- ctl.present(alert, animated: true, completion: nil)
- }
- }
- }
- extension QRCodeScanView: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
- public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
- picker.dismiss(animated: true) {
- guard let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage else { return }
- if let res = image.decodeQRCodeInImage() {
- self.qrscanner?.stopScan()
- self.qrmaskView?.stopAnimation()
- self.delegate?.scanView(self,
- receivedScanResult: QRCodeScanResult(metadataType: AVMetadataObject.ObjectType.qr.rawValue,
- result: res))
- } else {
- let error = NSError(domain: "decode qr code error",
- code: 101,
- userInfo: nil)
- self.delegate?.scanView(self,
- didFinshWithError: error)
- }
- self.indicatorView.stopAnimating()
- }
- }
-
- public func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
- picker.dismiss(animated: true, completion: nil)
- }
- }
- extension UIImage {
-
-
-
- public func decodeQRCodeInImage() -> String? {
- guard let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: nil),
- let cgImage1 = self.cgImage else { return nil }
- let result = detector.features(in: CIImage(cgImage: cgImage1), options: [CIDetectorAccuracy: CIDetectorAccuracyHigh])
- guard let first = (result as? [CIQRCodeFeature])?.first else { return nil }
- return first.messageString
- }
- }
|