下面就是详细讲解iOS自带原生二维码扫描的实现的完整攻略:
一、引入AVFoundation库
首先,我们需要引入AVFoundation库,来实现二维码扫描。在xcode中选择你项目的targets中的Build Phases,在Link Binary With Libraries中添加AVFoundation.framework。
二、继承AVCaptureSession,创建二维码捕捉器
我们需要继承AVCaptureSession,并创建一个二维码捕捉器来扫描二维码。可以看下面的示例:
import AVFoundation
class QRCodeScanner {
let captureSession = AVCaptureSession()
var previewLayer: AVCaptureVideoPreviewLayer?
init() {
guard let captureDevice = AVCaptureDevice.default(for: .video),
let input = try? AVCaptureDeviceInput(device: captureDevice) else {
return
}
let captureMetadataOutput = AVCaptureMetadataOutput()
captureSession.addInput(input)
captureSession.addOutput(captureMetadataOutput)
captureMetadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
captureMetadataOutput.metadataObjectTypes = [.qr]
let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
previewLayer.videoGravity = .resizeAspectFill
self.previewLayer = previewLayer
}
}
以上代码中,我们使用AVCaptureSession来创建了一个二维码捕捉器QRCodeScanner。先检测一下设备是否有摄像头,并创建AVCaptureDeviceInput输入设备。然后,创建AVCaptureMetadataOutput对象来检测捕捉到的二维码。最后,创建了一个AVCaptureVideoPreviewLayer预览图层并添加到self.previewLayer中。
三、实现AVCaptureMetadataOutputObjectsDelegate代理方法
接下来,我们需要实现AVCaptureMetadataOutputObjectsDelegate代理方法,来处理捕捉到的二维码。具体代码如下:
extension QRCodeScanner: AVCaptureMetadataOutputObjectsDelegate {
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
guard let metadataObject = metadataObjects.first as? AVMetadataMachineReadableCodeObject,
let stringValue = metadataObject.stringValue,
metadataObject.type == .qr else {
return
}
// 二维码扫描成功,可以在这里执行回调
}
}
以上代码中,我们处理捕捉到的AVMetadataObject,将其转换为二维码AVMetadataMachineReadableCodeObject对象,并获取到二维码的stringValue,来完成二维码的扫描。如果扫描的不是二维码,则直接返回。
四、启动二维码扫描
在上面的QRCodeScanner实现中,我们创建好了AVCaptureSession的输入和输出,以及预览图层。接下来,启动二维码扫描即可:
class ViewController: UIViewController {
private var qrCodeScanner: QRCodeScanner!
override func viewDidLoad() {
super.viewDidLoad()
qrCodeScanner = QRCodeScanner()
guard let previewLayer = qrCodeScanner.previewLayer else { return }
previewLayer.frame = view.layer.bounds
view.layer.addSublayer(previewLayer)
qrCodeScanner.captureSession.startRunning()
}
}
在上面代码中,我们创建了一个QRCodeScanner对象qrCodeScanner,并把预览图层添加到UIViewController的view上。最后,启动QRCodeScanner的捕捉器captureSession即可。
五、示例说明
接下来,我给你两个示例,具体实现请参考上面的完整攻略:
示例1:在UIAlertController中展示扫描到的二维码
在QRCodeScanner中实现接口扫描结束的回调
class QRCodeScanner {
var onQRCodeScanned: ((String) -> Void)?
// ...
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
guard let metadataObject = metadataObjects.first as? AVMetadataMachineReadableCodeObject,
let stringValue = metadataObject.stringValue,
metadataObject.type == .qr else {
return
}
// 扫描到二维码,执行回调
onQRCodeScanned?(stringValue)
}
}
在UIViewController中弹出UIAlertController,展示扫描到的二维码
class ViewController: UIViewController {
private var qrCodeScanner: QRCodeScanner!
override func viewDidLoad() {
super.viewDidLoad()
qrCodeScanner = QRCodeScanner()
qrCodeScanner.onQRCodeScanned = { [weak self] qrCodeString in
self?.showQRCodeInfo(qrCodeString)
}
guard let previewLayer = qrCodeScanner.previewLayer else { return }
previewLayer.frame = view.layer.bounds
view.layer.addSublayer(previewLayer)
qrCodeScanner.captureSession.startRunning()
}
private func showQRCodeInfo(_ qrCodeInfo: String) {
let alertController = UIAlertController(title: "扫描到的二维码", message: qrCodeInfo, preferredStyle: .alert)
let okAction = UIAlertAction(title: "确定", style: .default, handler: nil)
alertController.addAction(okAction)
present(alertController, animated: true, completion: nil)
}
}
示例2:在UITableView中展示扫描到的二维码
在QRCodeScanner中实现接口扫描结束的回调
class QRCodeScanner {
var onQRCodeScanned: ((String) -> Void)?
// ...
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
guard let metadataObject = metadataObjects.first as? AVMetadataMachineReadableCodeObject,
let stringValue = metadataObject.stringValue,
metadataObject.type == .qr else {
return
}
// 扫描到二维码,执行回调
onQRCodeScanned?(stringValue)
}
}
在UIViewController中添加UITableView,并更新数据源展示二维码信息
class ViewController: UIViewController {
private var qrCodeScanner: QRCodeScanner!
private var qrCodeStrings = [String]() {
didSet {
tableView.reloadData()
}
}
private let tableView = UITableView()
override func viewDidLoad() {
super.viewDidLoad()
qrCodeScanner = QRCodeScanner()
qrCodeScanner.onQRCodeScanned = { [weak self] qrCodeString in
self?.qrCodeStrings.append(qrCodeString)
}
guard let previewLayer = qrCodeScanner.previewLayer else { return }
previewLayer.frame = view.layer.bounds
view.layer.addSublayer(previewLayer)
qrCodeScanner.captureSession.startRunning()
setupTableView()
}
private func setupTableView() {
view.addSubview(tableView)
tableView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
tableView.topAnchor.constraint(equalTo: view.topAnchor),
tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
])
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "qrCodeCell")
tableView.dataSource = self
}
}
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return qrCodeStrings.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "qrCodeCell", for: indexPath)
let qrCodeString = qrCodeStrings[indexPath.row]
cell.textLabel?.text = qrCodeString
return cell
}
}
以上示例代码很简单,你可以尝试在自己的项目中按照上述方法实现iOS自带原生二维码扫描。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:iOS自带原生二维码扫描的实现 - Python技术站