サーチ…
前書き
QR(クイックレスポンス)コードは、機械可読光学ラベルに広く使用されている2次元バーコードです。 iOSは、iOS 7以降のAVFoundationフレームワークを使用してQRコードを読み取る方法を提供しています。このフレームワークは、カメラをセットアップ/オープンし、カメラフィードからQRコードを読み取るAPIのセットを提供します。
QRをスキャンしてビデオ入力を表示するUIViewController
import AVFoundation
class QRScannerViewController: UIViewController,
AVCaptureMetadataOutputObjectsDelegate {
func viewDidLoad() {
self.initCaptureSession()
}
private func initCaptureSession() {
let captureDevice = AVCaptureDevice
.defaultDevice(withMediaType: AVMediaTypeVideo)
do {
let input = try AVCaptureDeviceInput(device: captureDevice)
let captureMetadataOutput = AVCaptureMetadataOutput()
self.captureSession?.addOutput(captureMetadataOutput)
captureMetadataOutput.setMetadataObjectsDelegate(self,
queue: DispatchQueue.main)
captureMetadataOutput
.metadataObjectTypes = [AVMetadataObjectTypeQRCode]
self.videoPreviewLayer =
AVCaptureVideoPreviewLayer(session: self.captureSession)
self.videoPreviewLayer?
.videoGravity = AVLayerVideoGravityResizeAspectFill
self.videoPreviewLayer?.frame =
self.view.layer.bounds
self._viewController?.view.layer
.addSublayer(videoPreviewLayer!)
self.captureSession?.startRunning()
} catch {
//TODO: handle input open error
}
}
private func dismissCaptureSession() {
if let running = self.captureSession?.isRunning, running {
self.captureSession?.stopRunning()
}
self.captureSession = nil
self.videoPreviewLayer?.removeFromSuperLayer()
self.videoPreviewLayer = nil
}
func captureOutput(_ captureOutput: AVCaptureOutput,
didOutputMetadataObjects metadataObjects: [Any]!,
from connection: AVCaptureConnection) {
guard metadataObjects != nil && metadataObjects.count != 0 else {
//Nothing captured
return
}
if let metadataObj =
metadataObjects[0] as? AVMetadataMachineReadableCodeObject {
guard metadataObj.type == AVMetadataObjectTypeQRCode else {
return
}
let barCodeObject = videoPreviewLayer?
.transformedMetadataObject(for:
metadataObj as AVMetadataMachineReadableCodeObject)
as! AVMetadataMachineReadableCodeObject
if let qrValue = metadataObj.stringValue {
self.handleQRRead(value: qrValue)
}
}
}
private handleQRRead(value: String) {
//TODO: Handle the read qr
}
private captureSession: AVCaptureSession?
private videoPreviewLayer: AVCaptureVideo
}
handleQRRead - 正常なスキャンでinitCaptureSession - QRとカメラ入力のスキャンを初期化するdismissCaptureSession - カメラ入力を非表示にしてスキャンを停止する
AVFoudationフレームワークによるQRコードのスキャン
iOS 7より前にQRコードをスキャンする場合、 zBarやzXingなどのサードパーティのフレームワークやライブラリに依存する必要があるかもしれません。しかし、Appleはバーコードを読み取るためにiOS 7からAVCaptureMetaDataOutputを導入しAVCaptureMetaDataOutput 。
AVFoundationを使用してQRコードを読み取るには、 AVCaptureSessionをセットアップ/作成し、 captureOutput:didOutputMetadataObjects:fromConnection: delegateメソッドを使用する必要があります。
ステップ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メソッドにvideoPreviewLayerます。
let barCodeObject = videoPreviewLayer?.transformedMetadataObject(for: metadataObj)
qrCodeFrameView?.frame = barCodeObject!.bounds