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 许可下可用,该许可允许商业用途、修改、分发和私人用途。 随时随地随意使用它!