はじめに
QRコードの読み取りはiOSアプリで頻繁に登場する機能です。
カメラをQRコードに向けて読み取る方法一般的です
しかし、画面に表示されているQRコードはカメラ向けられず、困った経験のある方もいるのではないでしょうか?
今回は、画像データとしてのQRコードを読み取る方法を紹介します。
環境
- OS: macOS Sonoma 14.7.1
- XCode: 16.2.0
実装方針
VisionフレームワークにあるNVImageRequestHandlerとVNDetectBarcodesRequestを利用します。
VNDetectBarcodesRequestでは、処理を待つためにクロージャーを利用しなければなりませんが、今回はwithCheckedThrowingContinuation
を利用してasync関数として定義することにします。
VNImageRequestHandler
VNImageRequestHandlerを利用すると、単一の画像に対して1つ以上の処理をリクエストできます。
イニシャライザに画像データを渡す形で初期化し、perform
メゾットを利用することで処理をリクエストできます。
イニシャライザは、渡す画像データの型によって複数種類用意されており、CIImage
、UIImage
, Data
などを利用できます。
VNDetectBarcodesRequest
VNDetectBarcodesRequest
はVisionフレームワークによって提供されており、画像内のバーコード検出機能を提供しています。
このクラスをVNImageRequestHandler.performの引数とすることで、画像データの解析時に任意の処理を指せることができます
実装
サンプルとして、引数にQRコード画像をData型に変換したものを渡すと、QRコードのPayloadを返す関数を作成してみます。
func detectQRCode(imageData: Data) async throws -> String {
// withCheckedThrowingContinuationを利用して、asyncな関数に変換
return try await withCheckedThrowingContinuation { continuation in
// VNDetectBarcodesrequestを利用して、画像解析時の処理を定義する
let request = VNDetectBarcodesRequest { request, error in
if let error {
continuation.resume(throwing: error)
return
}
guard let results = request.results as? [VNBarcodeObservation],
let payload = results.first?.payloadStringValue else {
continuation.resume(throwing: HogeError.payloadNotFound) // 読み込めない場合には任意のえらーをthrowする
return
}
continuation.resume(returning: payload)
}
// VNImagerequestHandlerのイニシャライザに、解析したいQRコード画像のデータを渡す
let handler = VNImageRequestHandler(data: imageData, options: [:])
do {
// perform関数の実行によって解析を開始し、NVDetectBarcodesRequestに定義した内容に従って処理が行われる
try handler.perform([request])
} catch {
continuation.resume(throwing: error)
}
}
}
まとめ
要件によってはカメラからのQRコード読み込みと合わせて実装することで、よりQRコード読み込みを便利にできると思います!
実装コストも低いので是非試してみてください!