MTBBarcodeScanner
这是一个轻量级、易于使用的 iOS 8+ 条形码扫描库,它构建在 Apple 的优秀 AVFoundation 框架之上,并将随着 Apple 的发布持续更新。
使用这个库,你可以
- 提供一个自定义的 UIView 用于显示相机输入
- 读取任意数量条形码后停止
- 同时读取屏幕上的多个代码(仅2D条形码)
- 通过 block 无缝读取代码,包括字符串值和预览中的位置
- 轻松切换前后摄像头
- 切换设备闪光灯的开关
- 冻结和解除捕获以显示从相机拍摄的静态图像
查看示例项目,了解如何捕获单个代码、多个代码,或在高实时预览中突出显示有效或无效的有效代码。
示例条形码
安装
CocoaPods
MTBBarcodeScanner可以通过CocoaPods安装,在您的Podfile中添加以下行
pod "MTBBarcodeScanner"
Carthage
Carthage是一个去中心化的依赖管理器,它可以构建您的依赖关系并为您提供二进制框架。
您可以使用以下命令通过Homebrew安装Carthage
$ brew update
$ brew install carthage
要在Carthage的帮助下将MTBBarcodeScanner整合到您的Xcode项目中,请在您的Cartfile
中指定它
github "mikebuss/MTBBarcodeScanner"
运行carthage update
以构建框架,并将构建好的MTBBarcodeScanner.framework
文件拖拽到您的Xcode项目中。
手动
如果您想不使用依赖管理器,可以下载以下两个文件并将它们添加到您的项目中
Objective-C项目中的使用
要导入库: #import "MTBBarcodeScanner.h"
初始化
要初始化一个MTBBarcodeScanner
实例
scanner = [[MTBBarcodeScanner alloc] initWithPreviewView:self.previewView];
其中previewView
是用于显示摄像头部输入的那个UIView
。
如果您只想扫描某些MetaObjectTypes,您可以使用initWithMetadataObjectTypes:previewView:
方法进行初始化
s = [[MTBBarcodeScanner alloc] initWithMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]
previewView:self.previewView];
iOS 10及以后版本
如果您在iOS 10及以后的版本中使用MTBBarcodeScanner
库,您需要包含以下Info.plist
密钥以请求相机权限,否则应用会崩溃
<key>NSCameraUsageDescription</key>
<string>Can we access your camera in order to scan barcodes?</string>
当然,您也可以在此处设置自己的(本地化)消息。要了解更多关于iOS中的隐私密钥信息,请查看苹果官方文档。
扫描
读取第一段代码并停止扫描
注意:为了避免相机 feeds 中的延迟,请在使用 viewDidAppear 初始化而不仅是 viewDidLoad 时开始扫描。
[MTBBarcodeScanner requestCameraPermissionWithSuccess:^(BOOL success) {
if (success) {
NSError *error = nil;
[self.scanner startScanningWithResultBlock:^(NSArray *codes) {
AVMetadataMachineReadableCodeObject *code = [codes firstObject];
NSLog(@"Found code: %@", code.stringValue);
[self.scanner stopScanning];
} error:&error];
} else {
// The user denied access to the camera
}
}];
如果相机对准了多个二维码,您还可以读取所有这些码
NSError *error = nil;
[self.scanner startScanningWithResultBlock:^(NSArray *codes) {
for (AVMetadataMachineReadableCodeObject *code in codes) {
NSLog(@"Found code: %@", code.stringValue);
}
[self.scanner stopScanning];
} error:&error];
注意:这仅适用于二维条码,因为一维条码只能逐个读取。请参见相关苹果文档。
持续读取并仅输出唯一的码
NSError *error = nil;
[self.scanner startScanningWithResultBlock:^(NSArray *codes) {
for (AVMetadataMachineReadableCodeObject *code in codes) {
if ([self.uniqueCodes indexOfObject:code.stringValue] == NSNotFound) {
[self.uniqueCodes addObject:code.stringValue];
NSLog(@"Found unique code: %@", code.stringValue);
}
}
} error:&error];
回调块
配置 MTBBarcodeScanner 的另一种方法是直接配置块,如下所示
self.scanner.didStartScanningBlock = ^{
NSLog(@"The scanner started scanning! We can now hide any activity spinners.");
};
self.scanner.resultBlock = ^(NSArray *codes){
NSLog(@"Found these codes: %@", codes);
};
self.scanner.didTapToFocusBlock = ^(CGPoint point){
NSLog(@"The user tapped the screen to focus. \
Here we could present a view at %@", NSStringFromCGPoint(point));
};
[self.scanner startScanning];
如果您想在 MTBBarcodeScanner 初始化时显示旋转器,这很有用。
如果您想在这些块中引用 self
,请记住使用弱引用以避免循环引用
__weak MyViewController *weakSelf = self;
self.scanner.resultBlock = ^(NSArray *codes){
[weakSelf drawOverlaysOnCodes:codes];
};
在 Swift 3+ 项目中使用
请查看仓库中的 SwiftExampleViewController.swift
文件,该文件包含此功能的有效示例。
import UIKit
import MTBBarcodeScanner
class SwiftExampleViewController: UIViewController {
@IBOutlet var previewView: UIView!
var scanner: MTBBarcodeScanner?
override func viewDidLoad() {
super.viewDidLoad()
scanner = MTBBarcodeScanner(previewView: previewView)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
MTBBarcodeScanner.requestCameraPermission(success: { success in
if success {
do {
try self.scanner?.startScanning(resultBlock: { codes in
if let codes = codes {
for code in codes {
let stringValue = code.stringValue!
print("Found code: \(stringValue)")
}
}
})
} catch {
NSLog("Unable to start scanning")
}
} else {
UIAlertView(title: "Scanning Unavailable", message: "This app does not have permission to access the camera", delegate: nil, cancelButtonTitle: nil, otherButtonTitles: "Ok").show()
}
})
}
override func viewWillDisappear(_ animated: Bool) {
self.scanner?.stopScanning()
super.viewWillDisappear(animated)
}
}
要使用特定的相机(前置或后置)开始扫描
try self.scanner?.startScanning(with: .front,
resultBlock: { codes in
if let codes = codes {
for code in codes {
let stringValue = code.stringValue!
print("Found code: \(stringValue)")
}
}
在 Swift 2.3 项目中使用
import UIKit
import MTBBarcodeScanner
class ViewController: UIViewController {
var scanner: MTBBarcodeScanner?
override func viewDidLoad() {
super.viewDidLoad()
scanner = MTBBarcodeScanner(previewView: self.view)
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
scanner?.startScanningWithResultBlock({ (codes) in
for code in codes {
print(code)
}
}, error: nil)
}
}
点击对焦
默认情况下,MTBBarcodeScanner 允许用户轻触屏幕来实现相机对焦。要禁用此功能,请将 allowTapToFocus
属性设置为 NO。要当用户轻触屏幕时收到通知,请为 didTapToFocusBlock
属性提供一个代码块,如下所示
self.scanner.didTapToFocusBlock = ^(CGPoint point){
NSLog(@"The user tapped the screen to focus. \
Here we could present a view at %@", NSStringFromCGPoint(point));
};
切换相机
使用扫描器上的 flipCamera
方法切换到另一侧的相机
- (IBAction)switchCameraTapped:(id)sender {
[self.scanner flipCamera];
}
或者直接使用 setCamera:error
指定相机,如下所示
NSError *error = nil;
MTBBarcodeScanner *scanner = [[MTBBarcodeScanner alloc] initWithPreviewView:_previewView];
[scanner setCamera:MTBCameraFront error:&error];
这些示例可以在演示项目中找到。
冻结捕获
在某些情况下,您可能希望拍摄条码时冻结视频流。为此,请调用 freezeCapture
和 unfreezeCapture
方法。
限制扫描区域
要限制条码可扫描的屏幕部分,请在 didStartScanning
回调块中设置 MTBBarcodeScanner 的 scanRect
属性。请参见 MTBAdvancedExampleViewController
以获取此功能的示例。
__weak MTBAdvancedExampleViewController *weakSelf = self;
self.scanner.didStartScanningBlock = ^{
weakSelf.scanner.scanRect = weakSelf.viewOfInterest.frame;
};
控制闪光灯
要控制闪光灯,请设置 torchMode
属性或调用 toggleTorch
方法。
可用值包括
MTBTorchModeOff,
MTBTorchModeOn,
MTBTorchModeAuto
捕获静态图片
在开始扫描后,调用 captureStillImage:
方法来捕获静态图片。
设计考虑
本库的主要目标是
- 提供易于使用的条码扫描界面
- 尽可能少地对扫描过程做假设
- 不假设用户每次只想要扫描一个条码
- 不假设相机输入视图应该具有特定的尺寸
- 不假设扫描过程将有自己的视图控制器
开发者
Mike Buss
许可证
MTBBarcodeScanner遵循MIT许可证。有关更多信息,请参阅LICENSE文件。