ScanKit 是一个简单的 SwiftUI 包,用于使用 Apple 的 Vision Framework 扫描各种机器可读代码。
ScanKit 有两种形式:视图-模型对,或者是一个易于插入的 SwiftUI 视图。
在使用任何一种形式之前,您应该确保您的项目能够访问摄像头。
iOS 和 macOS:您必须在您的 info.plist 文件中包含“Privacy - Camera Usage Description”,或者 NSCameraUsageDescription。
macOS:必须在“Hardened Runtime”中的“Resource Access”下选择“Camera”。
ScannerView 是一个即插即用的 SwiftUI 代码扫描器,它将结果作为完成块返回。 它接受以下参数:
symbology:要扫描的 Apple VNBarcodeSymbology 种类之一。showViewfinder:一个 Boolean 值,指示是否在摄像头预览上显示“取景器”符号。isScanning:一个 Boolean 绑定,指示是否扫描摄像头 feed 以查找代码。 当 false 时,预览将继续可用,但在 true 之前,不会向完成块发送进一步的结果。如果 ScannerView 包含在某些 Navigation 容器中,它将向工具栏发送两个按钮。
在 macOS 上,摄像头选择器显示所有可用摄像头,包括连续互通相机。 在 iOS 上,摄像头切换按钮在前置和后置摄像头之间切换。
ScannerView 的完成块返回一个 Result<String, ScanKitError> 流。 ScanKitError 可以是:
notAuthorized,表示未授权摄像头访问。visionFailure,表示初始化以某种方式失败。 请查看日志以获取更多详细信息。最小示例
@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)
}
}
为了获得更自定义的体验,ScanKit 公开了一个独特的视图-模型组合,即 ScanKitPreview 和 ScanKitCamera。
ScanKitPreview 是 AVCapturePreviewLayer 周围的可表示包装器,可以显示从 ScanKitCamera 返回的 feed。
ScanKitCamera 直接与 AVFoundation 和 Vision 交互,以处理可用的捕获设备和 Vision 请求。 它是一个 ObservableObject,可以在其变量之一发生更改时更新视图。
结果通过 AsyncThrowingStream 从 ScanKitCamera 作为 String 进行流式传输。 当 ScanKitCamera().isScanning 设置为 false 或遇到错误时,流结束。 要一次仅扫描一个代码,只需在收到第一个结果后立即将 isScanning 设置为 false。
resultStream 只能抛出两种类型的错误:
notAuthorized,表示未授权摄像头访问。visionFailure,表示初始化以某种方式失败。 请查看日志以获取更多详细信息。您的 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 许可下可用,该许可允许商业用途、修改、分发和私人用途。 随时随地随意使用它!