iOS 实现扫一扫功能要用到如下几个对象:
var device: AVCaptureDevice!//设备
var input: AVCaptureDeviceInput!//输入
var output: AVCaptureMetadataOutput!//输出
var session: AVCaptureSession!//连接输出输入
var preview: AVCaptureVideoPreviewLayer!//页面显示
然后基本配置如下:
扫描结果的代理:
下面贴上所有代码:
import UIKit
import AVFoundation
class ScanQRCodeViewController: BaseViewController {
var device: AVCaptureDevice!
var input: AVCaptureDeviceInput!
var output: AVCaptureMetadataOutput!
var session: AVCaptureSession!
var preview: AVCaptureVideoPreviewLayer!
lazy var loading: UIActivityIndicatorView = {
let view = UIActivityIndicatorView(activityIndicatorStyle: .White)
view.frame = CGRect(x: 0, y: 0, width: 20, height: 20)
view.center = CGPoint(x: self.view.center.x, y: self.view.center.y - 100)
view.hidesWhenStopped = true
self.view.addSubview(view)
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.grayColor()
/**
配置扫一扫
*/
setupCamera()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func setupCamera() {
loading.startAnimating()
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0)) {
self.device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
do { self.input = try AVCaptureDeviceInput(device: self.device) } catch { }
self.output = AVCaptureMetadataOutput()
self.output.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
self.session = AVCaptureSession()
self.session.sessionPreset = AVCaptureSessionPresetHigh
if self.session.canAddInput(self.input) {
self.session.addInput(self.input)
}
if self.session.canAddOutput(self.output) {
self.session.addOutput(self.output)
}
self.output.metadataObjectTypes = [AVMetadataObjectTypeQRCode]
self.preview = AVCaptureVideoPreviewLayer(session: self.session)
self.preview.frame = self.view.bounds
self.preview.videoGravity = AVLayerVideoGravityResizeAspectFill
dispatch_async(dispatch_get_main_queue(), {
self.loading.stopAnimating()
self.view.layer.addSublayer(self.preview)
let rect = CGRect(x: (kScreenW - 250) / 2, y: (kScreenH - 400) / 2, width: 250, height: 250) // 可以扫描的区域
let maskView = UIView(frame: self.view.bounds)
maskView.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.5)
self.view.addSubview(maskView)
// 配置不能扫描区域的遮罩
let path = UIBezierPath(rect: self.view.bounds)
path.appendPath(UIBezierPath(rect: rect).bezierPathByReversingPath())
let shapeLayer = CAShapeLayer()
shapeLayer.path = path.CGPath
maskView.layer.mask = shapeLayer
self.output.rectOfInterest = self.preview.metadataOutputRectOfInterestForRect(rect) // 把layer中的坐标系转换成output的坐标系
let scanAreaImageView = UIImageView(frame: rect) // 扫描框的图片
scanAreaImageView.image = UIImage(named: "contact_scanframe")
self.view.addSubview(scanAreaImageView)
/// 上下扫动条
let sweepLineView = UIImageView(frame: CGRect(x: 1, y: 20, width: 248, height: 2))
sweepLineView.image = UIImage(named: "line")
scanAreaImageView.addSubview(sweepLineView)
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(1)
UIView.setAnimationRepeatAutoreverses(true)
UIView.setAnimationRepeatCount(10000)
UIView.setAnimationCurve(.EaseInOut)
sweepLineView.frame = CGRect(x: 1, y: 230, width: 248, height: 2)
UIView.commitAnimations()
self.session.startRunning() // 开始扫描
})
}
}
// }
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
extension ScanQRCodeViewController: AVCaptureMetadataOutputObjectsDelegate {
func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {
var stringValue = ""
if metadataObjects.count > 0 {
dPrint(metadataObjects)
stringValue = metadataObjects[0].stringValue
}
session.stopRunning()
dPrint(stringValue)
}
}
所需要的图片: