使用 AVFoudation 框架掃描 QR 碼
在 iOS 7 之前,當你想要掃描 QR 碼時,我們可能需要依賴第三方框架或庫,如 zBar 或 zXing 。但是 Apple 從 iOS 7 中引入了 AVCaptureMetaDataOutput
來讀取條形碼。
要使用 AVFoundation
讀取 QR 碼,我們需要設定/建立 AVCaptureSession
並使用 captureOutput:didOutputMetadataObjects:fromConnection:
委託方法。
步驟 1
匯入 AVFoundation
框架並確認 AVCaptureMetadataOutputObjectsDelegate
協議
import AVFoundation
class ViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate
第 2 步
QR 碼讀取完全基於視訊捕獲。因此,要捕獲連續視訊,請建立一個 AVCaptureSession
並設定裝置輸入和輸出。在檢視控制器 viewDidLoad
方法中新增以下程式碼
// Create an instance of the AVCaptureDevice and provide the video as the media type parameter.
let captureDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
do {
// Create an instance of the AVCaptureDeviceInput class using the device object and intialise capture session
let input = try AVCaptureDeviceInput(device: captureDevice)
captureSession = AVCaptureSession()
captureSession?.addInput(input)
// Create a instance of AVCaptureMetadataOutput object and set it as the output device the capture session.
let captureMetadataOutput = AVCaptureMetadataOutput()
captureSession?.addOutput(captureMetadataOutput)
// Set delegate with a default dispatch queue
captureMetadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
//set meta data object type as QR code, here we can add more then one type as well
captureMetadataOutput.metadataObjectTypes = [AVMetadataObjectTypeQRCode]
// Initialize the video preview layer and add it as a sublayer to the viewcontroller view's layer.
videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
videoPreviewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
videoPreviewLayer?.frame = view.layer.bounds
view.layer.addSublayer(videoPreviewLayer!)
// Start capture session.
captureSession?.startRunning()
} catch {
// If any error occurs, let the user know. For the example purpose just print out the error
print(error)
return
}
第 3 步
實現 AVCaptureMetadataOutputObjectsDelegate
委託方法來讀取 QR 碼
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {
// Check if the metadataObjects array contains at least one object. If not no QR code is in our video capture
if metadataObjects == nil || metadataObjects.count == 0 {
// NO QR code is being detected.
return
}
// Get the metadata object and cast it to `AVMetadataMachineReadableCodeObject`
let metadataObj = metadataObjects[0] as! AVMetadataMachineReadableCodeObject
if metadataObj.type == AVMetadataObjectTypeQRCode {
// If the found metadata is equal to the QR code metadata then get the string value from meta data
let barCodeObject = videoPreviewLayer?.transformedMetadataObject(for: metadataObj)
if metadataObj.stringValue != nil {
// metadataObj.stringValue is our QR code
}
}
}
這裡後設資料物件也可以為你提供在相機源上讀取的 QR 碼的界限。要獲取邊界,只需將後設資料物件傳遞給 videoPreviewLayer
的 transformedMetadataObject
方法,如下所示。
let barCodeObject = videoPreviewLayer?.transformedMetadataObject(for: metadataObj)
qrCodeFrameView?.frame = barCodeObject!.bounds