SwiftUI - 在 macOS 应用程序中扫描二维码
SwiftUI - scanning QR codes in the macOS app
我正在开发一个 Mac 应用程序,它将从相机读取 QR 码,然后从中读取文本。
不幸的是,CodeScanner 包仅适用于 iOS,并且没有调用的方法:
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection)
当然,要使用它,必须包含 AVCaptureMetadataOutputObjectsDelegate - 不幸的是,此协议在 macOS 上不可用。
有什么方法可以使用 SwiftUI 创建 macOS 二维码扫描器吗?
我目前有一个 Mac内置的图书相机预览,但我想念缺少捕捉 QR 码的东西:
final class PlayerContainerView: NSViewRepresentable {
typealias NSViewType = PlayerView
let captureSession: AVCaptureSession
init(captureSession: AVCaptureSession) {
self.captureSession = captureSession
}
func makeNSView(context: Context) -> PlayerView {
return PlayerView(captureSession: captureSession)
}
func updateNSView(_ nsView: PlayerView, context: Context) {}
}
class PlayerView: NSView {
var previewLayer: AVCaptureVideoPreviewLayer?
init(captureSession: AVCaptureSession) {
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
super.init(frame: .zero)
setupLayer()
}
func setupLayer() {
previewLayer?.frame = self.frame
previewLayer?.contentsGravity = .resizeAspectFill
previewLayer?.videoGravity = .resizeAspectFill
previewLayer?.connection?.automaticallyAdjustsVideoMirroring = false
if let mirroringSupported = previewLayer?.connection?.isVideoMirroringSupported {
if mirroringSupported {
previewLayer?.connection?.automaticallyAdjustsVideoMirroring = false
previewLayer?.connection?.isVideoMirrored = true
}
}
layer = previewLayer
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
我找不到任何委托协议可以像 AVCaptureMetadataOutputObjectsDelegate 一样工作并允许我捕获元数据对象。
我也很惊讶 macOS AVFoundation
不支持 AVCaptureMetadataOutput
,但是 CoreImage
支持 QR 码,这对我有用:
let qrDetector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: nil)!
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
guard let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return }
let ciImage = CIImage(cvImageBuffer: imageBuffer)
let features = qrDetector.features(in: ciImage)
for feature in features {
let qrCodeFeature = feature as! CIQRCodeFeature
print("messageString \(qrCodeFeature.messageString!)")
}
}
可能有更有效的方法。
我正在开发一个 Mac 应用程序,它将从相机读取 QR 码,然后从中读取文本。
不幸的是,CodeScanner 包仅适用于 iOS,并且没有调用的方法:
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection)
当然,要使用它,必须包含 AVCaptureMetadataOutputObjectsDelegate - 不幸的是,此协议在 macOS 上不可用。
有什么方法可以使用 SwiftUI 创建 macOS 二维码扫描器吗?
我目前有一个 Mac内置的图书相机预览,但我想念缺少捕捉 QR 码的东西:
final class PlayerContainerView: NSViewRepresentable {
typealias NSViewType = PlayerView
let captureSession: AVCaptureSession
init(captureSession: AVCaptureSession) {
self.captureSession = captureSession
}
func makeNSView(context: Context) -> PlayerView {
return PlayerView(captureSession: captureSession)
}
func updateNSView(_ nsView: PlayerView, context: Context) {}
}
class PlayerView: NSView {
var previewLayer: AVCaptureVideoPreviewLayer?
init(captureSession: AVCaptureSession) {
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
super.init(frame: .zero)
setupLayer()
}
func setupLayer() {
previewLayer?.frame = self.frame
previewLayer?.contentsGravity = .resizeAspectFill
previewLayer?.videoGravity = .resizeAspectFill
previewLayer?.connection?.automaticallyAdjustsVideoMirroring = false
if let mirroringSupported = previewLayer?.connection?.isVideoMirroringSupported {
if mirroringSupported {
previewLayer?.connection?.automaticallyAdjustsVideoMirroring = false
previewLayer?.connection?.isVideoMirrored = true
}
}
layer = previewLayer
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
我找不到任何委托协议可以像 AVCaptureMetadataOutputObjectsDelegate 一样工作并允许我捕获元数据对象。
我也很惊讶 macOS AVFoundation
不支持 AVCaptureMetadataOutput
,但是 CoreImage
支持 QR 码,这对我有用:
let qrDetector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: nil)!
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
guard let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return }
let ciImage = CIImage(cvImageBuffer: imageBuffer)
let features = qrDetector.features(in: ciImage)
for feature in features {
let qrCodeFeature = feature as! CIQRCodeFeature
print("messageString \(qrCodeFeature.messageString!)")
}
}
可能有更有效的方法。