SwiftUI ScanKit

ScanKit 是一个简单的 SwiftUI 包,用于使用 Apple 的 Vision Framework 扫描各种机器可读代码。

SwiftUI ScanKit Logo Image

Swift Package Manager

入门指南

ScanKit 有两种形式:视图-模型对,或者是一个易于插入的 SwiftUI 视图。

在使用任何一种形式之前,您应该确保您的项目能够访问摄像头。

iOS 和 macOS:您必须在您的 info.plist 文件中包含“Privacy - Camera Usage Description”,或者 NSCameraUsageDescription

macOS:必须在“Hardened Runtime”中的“Resource Access”下选择“Camera”。

ScannerView

ScannerView 是一个即插即用的 SwiftUI 代码扫描器,它将结果作为完成块返回。 它接受以下参数:

如果 ScannerView 包含在某些 Navigation 容器中,它将向工具栏发送两个按钮。

在 macOS 上,摄像头选择器显示所有可用摄像头,包括连续互通相机。 在 iOS 上,摄像头切换按钮在前置和后置摄像头之间切换。

ScannerView 的完成块返回一个 Result<String, ScanKitError> 流。 ScanKitError 可以是:

最小示例

@State var scanning: Bool = true

ScannerView(for: .qr, isScanning: $scanning) { result in
    switch result {
        case .success(let string):
        // To only scan once, call `self.scanning = false` here
        print(string)
        case .failure(let error):
        print(error)
    }
}

ScanKitPreview & ScanKitCamera

为了获得更自定义的体验,ScanKit 公开了一个独特的视图-模型组合,即 ScanKitPreviewScanKitCamera

ScanKitPreviewAVCapturePreviewLayer 周围的可表示包装器,可以显示从 ScanKitCamera 返回的 feed。

ScanKitCamera 直接与 AVFoundationVision 交互,以处理可用的捕获设备和 Vision 请求。 它是一个 ObservableObject,可以在其变量之一发生更改时更新视图。

结果通过 AsyncThrowingStreamScanKitCamera 作为 String 进行流式传输。 当 ScanKitCamera().isScanning 设置为 false 或遇到错误时,流结束。 要一次仅扫描一个代码,只需在收到第一个结果后立即将 isScanning 设置为 false。

resultStream 只能抛出两种类型的错误:

您的 ScanKitCamera 对象中提供了各种变量和函数,允许您直接从 SwiftUI 与设备的摄像头进行交互。

类型 名称 目的
var (get) isCapturing 一个 Boolean 值,指示摄像头是否处于活动状态。
var (get/set) isScanning 一个 Boolean 值,指示摄像头是否正在扫描机器可读代码。
var (get) isTorchAvailable 一个 Boolean 值,指示当前摄像头是否有可用的手电筒。
var (get) isTorchOn 一个 Boolean 值,指示手电筒是否已打开。 如果没有手电筒,则始终为 false。
var (get) isUsingBackCamera 一个 Boolean 值,指示后置摄像头是否处于活动状态。 在 macOS 上,这始终为 false。
var (get) isUsingFrontCamera 一个 Boolean 值,指示前置摄像头是否处于活动状态。 在 macOS 上,这始终为 false。
var (get) resultsStream 一个 AsyncThrowingStream,呈现扫描操作的结果。
var (get/set) symbology 当前正在扫描的代码符号体系。
var (get) supportedSymbologies 所有支持的符号体系的数组。
func cycleCaptureDevices 循环显示可用摄像头。 在 iOS 上,这只是在前置摄像头和后置摄像头之间切换。
func getCamerasAsButtons 返回一个 View,其中包含所有可用摄像头作为单个 Button。 当按下时,每个 Button 都会将 ScanKitCamera 切换到该特定摄像头。 最好在 Menu 中调用此方法。
func toggleTorch 切换手电筒,如果可用。
func start 启动摄像头。 这会在 ScanKitPreview 中的 appear 期间自动调用。
func stop 停止摄像头。 这会在 ScanKitPreview 中的 disappear 期间自动调用。

最小示例

@StateObject camera = ScanKitCamera()

var body: some View {
    ScanKitPreview(camera: camera)
        .task {
            do {
                for try await result in camera.resultsStream {
                    print(result)
                }
            } catch let error {
                print(error)
            }
        }
}

可以参考 ScanView 的实现来获取灵感。

注意事项

应该提前指出,Vision Framework 不是处理机器可读代码的最有效方法。 但是,它是跨平台的。

如果您仅以 iOS 为目标,或者计划通过 Mac Catalyst 以 macOS 为目标,那么像 CodeScanner 这样的包,它利用 AVCaptureMetadataOutput,值得考虑。

许可

SwiftUI ScanKit 在 MIT 许可下可用,该许可允许商业用途、修改、分发和私人用途。 随时随地随意使用它!