空闲学习下AVFoundation中的AVCaptureSession,为了加深理解,写了一个识别二维码的demo。
首先 点我下载 demo~~ 一个页面的工程,大概五十代码左右。
实现
首先我们需要创建一个AVCaptureSession实例:
private lazy var session: AVCaptureSession = {
var session = AVCaptureSession()
var device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
var input: AVCaptureDeviceInput?
do {
input = try AVCaptureDeviceInput(device: device)
} catch {
print(error)
}
if input != nil {
session.addInput(input)
}
var output = AVCaptureMetadataOutput()
session.addOutput(output)
output.metadataObjectTypes = [AVMetadataObjectTypeQRCode]
output.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
return session
}()
创建session的时候,需要为它指定一个CaptureDevice,这里设置成视频类型,还需要CaptureDeviceInput和CaptureMetadataOutput,这里说明一下:
- AVCaptureDevice:输入设备
- AVCaptureInput:输入数据源
- AVCaptureOutput:输出数据源(AVCaptureMetadataOutput是它的子类)
- AVCaptureSession:协调输入与输出之间的数据流
通过AVCaptureVideoPreviewLayer实现预览功能:
fileprivate lazy var previewLayer: AVCaptureVideoPreviewLayer = {
var previewLayer = AVCaptureVideoPreviewLayer(session: self.session)
return previewLayer!
}()
这里需要指定具体的某一个session。
在代理方法中分析处理视频流:
fileprivate lazy var qrCodeFrameView: UIView = {
let view = UIView()
view.layer.borderColor = UIColor.blue.cgColor
view.layer.borderWidth = 2
return view
}()
// MARK: - AVCaptureMetadataOutputObjectsDelegate
extension ViewController: AVCaptureMetadataOutputObjectsDelegate {
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {
qrCodeFrameView.frame = .zero
for metadataObject in metadataObjects {
guard let object = metadataObject as? AVMetadataMachineReadableCodeObject else {
return
}
if object.type == AVMetadataObjectTypeQRCode {
guard let url = URL(string: object.stringValue) else {
return
}
let barCodeObject = previewLayer.transformedMetadataObject(for: object)
qrCodeFrameView.frame = barCodeObject!.bounds
UIApplication.shared.openURL(url)
}
}
}
}
qrCodeFrameView 的作用是在展示QRCode的位置,如果识别到QRCode,就显示一个浮层。当识别到数据对象是AVMetadataObjectTypeQRCode类型时,就会把QRCode的URL解析出来,并打开该URL。
注意,session是需要通过startRunning()方法来启动捕捉流的:
override func viewDidLoad() {
super.viewDidLoad()
previewLayer.frame = view.frame
view.layer.addSublayer(previewLayer)
session.startRunning()
view.addSubview(qrCodeFrameView)
view.bringSubview(toFront: qrCodeFrameView)
}
扩展
假如,你需要做一个扫码应用或者功能时,有一个功能应该是附带用到的,那就是3D Touch,比如qq、微信,都提供了扫一扫的3D Touch快捷功能。这里就不详细说了,实现起来还是比较简单的。
小结
学以致用,触类旁通。