$(MpiDebuggerDebuggerType) 我怎样才能在 iOS 上扫描条形码?

如何简单地扫描 iPhone 和/或 iPad 上的条形码?

146319 次浏览
$(MpiDebuggerDeployCommonRuntime) $(MpiDebuggerNetworkSecurityMode) $(MpiDebuggerSchedulerNode) $(MpiDebuggerSchedulerTimeout)

我们为 iPhone 开发了“条形码”应用程序。它能解码二维码。源代码可以从 Zxing 项目获得; 具体来说,您需要查看 IPhone 客户端核心库的部分 C + + 端口。这个端口有点旧,从大约0.9版本的 Java 代码开始,但应该仍然能够很好地工作。

$(MSBuild _ ExecutablePath)

如果您需要扫描其他格式,比如1D 格式,您可以将本项目中 Java 代码的端口继续移植到 C + + 。

$(MSBuildAllProjects)

编辑: 项目中的条形码和 iphone代码大约在2014年初退役。

$(MSBuildAssemblyVersion) $(MSBuildBinPath)

IPhone 摄像头的问题在于,第一代机型(使用量很大)有一个固定焦距的摄像头,在2英尺以下的距离内无法对焦拍照。图像是模糊和扭曲的,如果从更远的距离拍摄,没有足够的细节/信息从条形码。

$(MSBuildExtensionsPath) $(MSBuildExtensionsPath32)

一些公司已经开发了 iPhone 应用程序,可以通过使用先进的去模糊技术来适应这种情况。你可以在苹果应用商店找到这些应用程序: pic2shop,RedLaser 和 ShopSavvy。所有的公司都宣布他们也有 SDK 可用-一些免费或非常优惠的条件,检查一下。

$(MSBuildExtensionsPath64) $(MSBuildFrameworkToolsPath) $(MSBuildFrameworkToolsPath32)

如果支持 iPad 2或 iPod Touch 对你的应用程序很重要,我会选择条形码扫描器 SDK,它可以解码模糊图像中的条形码,比如我们的 iOS 和 Android 的 Scandit 条形码扫描器 SDK。解码模糊的条形码图像也有助于手机与自动对焦相机,因为用户不必等待自动对焦启动。

$(MSBuildFrameworkToolsPath64)

Scandit 提供了一个免费的社区价格计划,还有一个产品 API,可以很容易地将条形码编号转换为产品名称。

$(MSBuildFrameworkToolsRoot)

(免责声明: 我是 Scandit 的联合创始人)

$(MSBuildLoadMicrosoftTargetsReadOnly)

有两个主要的图书馆:

    $(MSBuildNodeCount)
  • ZXing 一个用 Java 编写的库,然后移植到 Objective C/C + + (只有 QR 代码)。另外一个到 ObjecC 的端口已经完成了,由 TheLevelUp 提供:

  • $(MSBuildProgramFiles32)
  • ZBar 一个用于读取条形码的开源软件,基于 C。

$(MSBuildProjectDefaultTargets) $(MSBuildProjectDirectory)

根据我的实验,ZBar 更加精确和快速比 ZXing,至少在 iPhone 上。

$(MSBuildProjectDirectoryNoRoot) $(MSBuildProject 扩展)

随着 iOS7的发布,您不再需要使用外部框架或库。从 EAN 的 QR 到 UPC 的几乎每一个代码。

$(MSBuildProjectExtensionsPath) $(MSBuildProjectFile)

只要看看 科技笔记和 AVFoundation 编程指南。 AVMetadataObjectTypeQRCode是你的朋友。

$(MSBuildProjectFullPath)

下面是一个很好的 教程,它一步一步地显示它: $(MSBuildProjectName) $(MSBuildRuntimeType) IPhone 二维码扫描库 iOS7

$(MSBuildRuntimeVersion)

只是一个如何设置它的小例子:

#pragma mark -
#pragma mark AVFoundationScanSetup


- (void) setupScanner;
{
self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];


self.input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];


self.session = [[AVCaptureSession alloc] init];


self.output = [[AVCaptureMetadataOutput alloc] init];
[self.session addOutput:self.output];
[self.session addInput:self.input];


[self.output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
self.output.metadataObjectTypes = @[AVMetadataObjectTypeQRCode];


self.preview = [AVCaptureVideoPreviewLayer layerWithSession:self.session];
self.preview.videoGravity = AVLayerVideoGravityResizeAspectFill;
self.preview.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);


AVCaptureConnection *con = self.preview.connection;


con.videoOrientation = AVCaptureVideoOrientationLandscapeLeft;


[self.view.layer insertSublayer:self.preview atIndex:0];
}
$(MSBuildSDKsPath)

你可以选择 ZBarSDK 来读取 QR 码和 ECN/ISBN 码集成起来很简单,试试下面的代码。

- (void)scanBarcodeWithZBarScanner
{
// ADD: present a barcode reader that scans from the camera feed
ZBarReaderViewController *reader = [ZBarReaderViewController new];
reader.readerDelegate = self;
reader.supportedOrientationsMask = ZBarOrientationMaskAll;


ZBarImageScanner *scanner = reader.scanner;
// TODO: (optional) additional reader configuration here


// EXAMPLE: disable rarely used I2/5 to improve performance
[scanner setSymbology: ZBAR_I25
config: ZBAR_CFG_ENABLE
to: 0];


//Get the return value from controller
[reader setReturnBlock:^(BOOL value) {


}

在 did FinishPickingMediaWithInfo 中我们得到条形码值。

$(MSBuildStartupDirectory)
    - (void) imagePickerController: (UIImagePickerController*) reader
didFinishPickingMediaWithInfo: (NSDictionary*) info
{
// ADD: get the decode results
id<NSFastEnumeration> results =
[info objectForKey: ZBarReaderControllerResults];
ZBarSymbol *symbol = nil;
for(symbol in results)
// EXAMPLE: just grab the first barcode
break;


// EXAMPLE: do something useful with the barcode data
barcodeValue = symbol.data;


// EXAMPLE: do something useful with the barcode image
barcodeImage =   [info objectForKey:UIImagePickerControllerOriginalImage];
[_barcodeIV setImage:barcodeImage];


//set the values for to TextFields
[self setBarcodeValue:YES];


// ADD: dismiss the controller (NB dismiss from the *reader*!)
[reader dismissViewControllerAnimated:YES completion:nil];
}

下面是一些简单的代码:

func scanbarcode()
{
view.backgroundColor = UIColor.blackColor()
captureSession = AVCaptureSession()


let videoCaptureDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
let videoInput: AVCaptureDeviceInput


do {
videoInput = try AVCaptureDeviceInput(device: videoCaptureDevice)
} catch {
return
}


if (captureSession.canAddInput(videoInput)) {
captureSession.addInput(videoInput)
} else {
failed();
return;
}


let metadataOutput = AVCaptureMetadataOutput()


if (captureSession.canAddOutput(metadataOutput)) {
captureSession.addOutput(metadataOutput)


metadataOutput.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
metadataOutput.metadataObjectTypes = [AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypePDF417Code]
} else {
failed()
return
}


previewLayer = AVCaptureVideoPreviewLayer(session: captureSession);
previewLayer.frame = view.layer.bounds;
previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
view.layer.addSublayer(previewLayer);
view.addSubview(closeBtn)
view.addSubview(backimg)


captureSession.startRunning();


}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}


func failed() {
let ac = UIAlertController(title: "Scanning not supported", message: "Your device does not support scanning a code from an item. Please use a device with a camera.", preferredStyle: .Alert)
ac.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
presentViewController(ac, animated: true, completion: nil)
captureSession = nil
}


override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)


if (captureSession?.running == false) {
captureSession.startRunning();
}
}


override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)


if (captureSession?.running == true) {
captureSession.stopRunning();
}
}


func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {
captureSession.stopRunning()


if let metadataObject = metadataObjects.first {
let readableObject = metadataObject as! AVMetadataMachineReadableCodeObject;


AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
foundCode(readableObject.stringValue);
}


// dismissViewControllerAnimated(true, completion: nil)
}


$(MSBuildToolsPath)
func foundCode(code: String) {
var createAccountErrorAlert: UIAlertView = UIAlertView()
createAccountErrorAlert.delegate = self
createAccountErrorAlert.title = "Alert"
createAccountErrorAlert.message = code
createAccountErrorAlert.addButtonWithTitle("ok")
createAccountErrorAlert.addButtonWithTitle("Retry")
createAccountErrorAlert.show()
NSUserDefaults.standardUserDefaults().setObject(code, forKey: "barcode")
NSUserDefaults.standardUserDefaults().synchronize()
ItemBarcode = code
print(code)
}


override func prefersStatusBarHidden() -> Bool {
return true
}


override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return .Portrait
}
$(MSBuildToolsPath32) $(MSBuildToolsPath64)

我相信这可以用 AVFramework 完成,下面是这样做的示例代码

import UIKit
import AVFoundation


class ViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate
{


@IBOutlet weak var lblQRCodeResult: UILabel!
@IBOutlet weak var lblQRCodeLabel: UILabel!


var objCaptureSession:AVCaptureSession?
var objCaptureVideoPreviewLayer:AVCaptureVideoPreviewLayer?
var vwQRCode:UIView?


override func viewDidLoad() {
super.viewDidLoad()
self.configureVideoCapture()
self.addVideoPreviewLayer()
self.initializeQRView()
}


func configureVideoCapture() {
let objCaptureDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
var error:NSError?
let objCaptureDeviceInput: AnyObject!
do {
objCaptureDeviceInput = try AVCaptureDeviceInput(device: objCaptureDevice) as AVCaptureDeviceInput


} catch let error1 as NSError {
error = error1
objCaptureDeviceInput = nil
}
objCaptureSession = AVCaptureSession()
objCaptureSession?.addInput(objCaptureDeviceInput as! AVCaptureInput)
let objCaptureMetadataOutput = AVCaptureMetadataOutput()
objCaptureSession?.addOutput(objCaptureMetadataOutput)
objCaptureMetadataOutput.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
objCaptureMetadataOutput.metadataObjectTypes = [AVMetadataObjectTypeQRCode]
}


func addVideoPreviewLayer() {
objCaptureVideoPreviewLayer = AVCaptureVideoPreviewLayer(session: objCaptureSession)
objCaptureVideoPreviewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
objCaptureVideoPreviewLayer?.frame = view.layer.bounds
self.view.layer.addSublayer(objCaptureVideoPreviewLayer!)
objCaptureSession?.startRunning()
self.view.bringSubviewToFront(lblQRCodeResult)
self.view.bringSubviewToFront(lblQRCodeLabel)
}


func initializeQRView() {
vwQRCode = UIView()
vwQRCode?.layer.borderColor = UIColor.redColor().CGColor
vwQRCode?.layer.borderWidth = 5
self.view.addSubview(vwQRCode!)
self.view.bringSubviewToFront(vwQRCode!)
}


func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {
if metadataObjects == nil || metadataObjects.count == 0 {
vwQRCode?.frame = CGRectZero
lblQRCodeResult.text = "QR Code wans't found"
return
}
let objMetadataMachineReadableCodeObject = metadataObjects[0] as! AVMetadataMachineReadableCodeObject
if objMetadataMachineReadableCodeObject.type == AVMetadataObjectTypeQRCode {
let objBarCode = objCaptureVideoPreviewLayer?.transformedMetadataObjectForMetadataObject(objMetadataMachineReadableCodeObject as AVMetadataMachineReadableCodeObject) as! AVMetadataMachineReadableCodeObject
vwQRCode?.frame = objBarCode.bounds;
if objMetadataMachineReadableCodeObject.stringValue != nil {
lblQRCodeResult.text = objMetadataMachineReadableCodeObject.stringValue
}
}
}
}
$(MSBuildToolsRoot) $(MSBuildToolsVersion)

您可以在下面找到另一个使用 Swift 4Xcode 9的本地 iOS 解决方案。此解决方案中使用的本机 AVFoundation框架。

$(MSBuildUserExtensionsPath)

第一部分是 UIViewController的一个子类,它具有与 AVCaptureSession相关的设置和处理函数。

import UIKit
import AVFoundation


class BarCodeScannerViewController: UIViewController {


let captureSession = AVCaptureSession()
var videoPreviewLayer: AVCaptureVideoPreviewLayer!
var initialized = false


let barCodeTypes = [AVMetadataObject.ObjectType.upce,
AVMetadataObject.ObjectType.code39,
AVMetadataObject.ObjectType.code39Mod43,
AVMetadataObject.ObjectType.code93,
AVMetadataObject.ObjectType.code128,
AVMetadataObject.ObjectType.ean8,
AVMetadataObject.ObjectType.ean13,
AVMetadataObject.ObjectType.aztec,
AVMetadataObject.ObjectType.pdf417,
AVMetadataObject.ObjectType.itf14,
AVMetadataObject.ObjectType.dataMatrix,
AVMetadataObject.ObjectType.interleaved2of5,
AVMetadataObject.ObjectType.qr]


override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
setupCapture()
// set observer for UIApplicationWillEnterForeground, so we know when to start the capture session again
NotificationCenter.default.addObserver(self,
selector: #selector(willEnterForeground),
name: .UIApplicationWillEnterForeground,
object: nil)
}


override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// this view is no longer topmost in the app, so we don't need a callback if we return to the app.
NotificationCenter.default.removeObserver(self,
name: .UIApplicationWillEnterForeground,
object: nil)
}


// This is called when we return from another app to the scanner view
@objc func willEnterForeground() {
setupCapture()
}


func setupCapture() {
var success = false
var accessDenied = false
var accessRequested = false


let authorizationStatus = AVCaptureDevice.authorizationStatus(for: .video)
if authorizationStatus == .notDetermined {
// permission dialog not yet presented, request authorization
accessRequested = true
AVCaptureDevice.requestAccess(for: .video,
completionHandler: { (granted:Bool) -> Void in
self.setupCapture();
})
return
}
if authorizationStatus == .restricted || authorizationStatus == .denied {
accessDenied = true
}
if initialized {
success = true
} else {
let deviceDiscoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera,
.builtInTelephotoCamera,
.builtInDualCamera],
mediaType: .video,
position: .unspecified)


if let captureDevice = deviceDiscoverySession.devices.first {
do {
let videoInput = try AVCaptureDeviceInput(device: captureDevice)
captureSession.addInput(videoInput)
success = true
} catch {
NSLog("Cannot construct capture device input")
}
} else {
NSLog("Cannot get capture device")
}
}
if success {
DispatchQueue.global().async {
self.captureSession.startRunning()
DispatchQueue.main.async {
let captureMetadataOutput = AVCaptureMetadataOutput()
self.captureSession.addOutput(captureMetadataOutput)
let newSerialQueue = DispatchQueue(label: "barCodeScannerQueue") // in iOS 11 you can use main queue
captureMetadataOutput.setMetadataObjectsDelegate(self, queue: newSerialQueue)
captureMetadataOutput.metadataObjectTypes = self.barCodeTypes
self.videoPreviewLayer = AVCaptureVideoPreviewLayer(session: self.captureSession)
self.videoPreviewLayer.videoGravity = .resizeAspectFill
self.videoPreviewLayer.frame = self.view.layer.bounds
self.view.layer.addSublayer(self.videoPreviewLayer)
}
}
initialized = true
} else {
// Only show a dialog if we have not just asked the user for permission to use the camera.  Asking permission
// sends its own dialog to th user
if !accessRequested {
// Generic message if we cannot figure out why we cannot establish a camera session
var message = "Cannot access camera to scan bar codes"
#if (arch(i386) || arch(x86_64)) && (!os(macOS))
message = "You are running on the simulator, which does not hae a camera device.  Try this on a real iOS device."
#endif
if accessDenied {
message = "You have denied this app permission to access to the camera.  Please go to settings and enable camera access permission to be able to scan bar codes"
}
let alertPrompt = UIAlertController(title: "Cannot access camera", message: message, preferredStyle: .alert)
let confirmAction = UIAlertAction(title: "OK", style: .default, handler: { (action) -> Void in
self.navigationController?.popViewController(animated: true)
})
alertPrompt.addAction(confirmAction)
self.present(alertPrompt, animated: true, completion: nil)
}
}
}


func handleCapturedOutput(metadataObjects: [AVMetadataObject]) {
if metadataObjects.count == 0 {
return
}


guard let metadataObject = metadataObjects.first as? AVMetadataMachineReadableCodeObject else {
return
}


if barCodeTypes.contains(metadataObject.type) {
if let metaDataString = metadataObject.stringValue {
captureSession.stopRunning()
displayResult(code: metaDataString)
return
}
}
}


func displayResult(code: String) {
let alertPrompt = UIAlertController(title: "Bar code detected", message: code, preferredStyle: .alert)
if let url = URL(string: code) {
let confirmAction = UIAlertAction(title: "Launch URL", style: .default, handler: { (action) -> Void in
UIApplication.shared.open(url, options: [:], completionHandler: { (result) in
if result {
NSLog("opened url")
} else {
let alertPrompt = UIAlertController(title: "Cannot open url", message: nil, preferredStyle: .alert)
let confirmAction = UIAlertAction(title: "OK", style: .default, handler: { (action) -> Void in
})
alertPrompt.addAction(confirmAction)
self.present(alertPrompt, animated: true, completion: {
self.setupCapture()
})
}
})
})
alertPrompt.addAction(confirmAction)
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: { (action) -> Void in
self.setupCapture()
})
alertPrompt.addAction(cancelAction)
present(alertPrompt, animated: true, completion: nil)
}


}
$(MSBuildVersion)

第二部分是 AVCaptureMetadataOutputObjectsDelegateUIViewController子类的扩展,在这里我们捕获获取的输出。

extension BarCodeScannerViewController: AVCaptureMetadataOutputObjectsDelegate {


func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
handleCapturedOutput(metadataObjects: metadataObjects)
}


}
$(MultiToolTask)

Swift 4.2的更新

$(NETFXKitsDir)

.UIApplicationWillEnterForeground变成 UIApplication.willEnterForegroundNotification

$(NETFXSDKDir) $(NuGetProps)

如果你正在用 Swift 4开发 iOS > 10.2,那么你可以试试我的解决方案。我混合了 这个这个教程,并提出了一个视图控制器扫描二维码和 print()它了。我还有一个开关在我的用户界面切换相机灯,可能也有帮助。目前我只在 iPhone SE 上测试过,如果它不能在较新的 iPhone 上运行,请告诉我。

$(NUMBER _ OF _ Processors)

给你:

import UIKit
import AVFoundation


class QRCodeScanner: UIViewController, AVCaptureMetadataOutputObjectsDelegate {


let captureSession: AVCaptureSession = AVCaptureSession()
var videoPreviewLayer: AVCaptureVideoPreviewLayer?
let qrCodeFrameView: UIView = UIView()
var captureDevice: AVCaptureDevice?


override func viewDidLoad() {
// Get the back-facing camera for capturing videos
let deviceDiscoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera, .builtInDualCamera], mediaType: AVMediaType.video, position: .back)


captureDevice = deviceDiscoverySession.devices.first
if captureDevice == nil {
print("Failed to get the camera device")
return
}


do {
// Get an instance of the AVCaptureDeviceInput class using the previous device object.
let input = try AVCaptureDeviceInput(device: captureDevice!)


// Set the input device on the capture session.
captureSession.addInput(input)


// Initialize a AVCaptureMetadataOutput object and set it as the output device to the capture session.
let captureMetadataOutput = AVCaptureMetadataOutput()
captureSession.addOutput(captureMetadataOutput)


// Set delegate and use the default dispatch queue to execute the call back
captureMetadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
captureMetadataOutput.metadataObjectTypes = [AVMetadataObject.ObjectType.qr]


// Initialize the video preview layer and add it as a sublayer to the viewPreview view's layer.


videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)


if let videoPreviewLayer = videoPreviewLayer {
videoPreviewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
videoPreviewLayer.frame = view.layer.bounds
view.layer.addSublayer(videoPreviewLayer)


// Start video capture.
captureSession.startRunning()


if let hasFlash = captureDevice?.hasFlash, let hasTorch = captureDevice?.hasTorch {
if hasFlash && hasTorch {
view.bringSubview(toFront: bottomBar)
try captureDevice?.lockForConfiguration()
}
}
}


// QR Code Overlay
qrCodeFrameView.layer.borderColor = UIColor.green.cgColor
qrCodeFrameView.layer.borderWidth = 2
view.addSubview(qrCodeFrameView)
view.bringSubview(toFront: qrCodeFrameView)


} catch {
// If any error occurs, simply print it out and don't continue any more.
print("Error: \(error)")
return
}
}


// MARK: Buttons and Switch


@IBAction func switchFlashChanged(_ sender: UISwitch) {
do {
if sender.isOn {
captureDevice?.torchMode = .on
} else {
captureDevice?.torchMode = .off
}
}
}


// MARK: AVCaptureMetadataOutputObjectsDelegate


func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {


// Check if the metadataObjects array is not nil and it contains at least one object.
if metadataObjects.count == 0 {
qrCodeFrameView.frame = CGRect.zero
return
}


// Get the metadata object.
let metadataObj = metadataObjects[0] as! AVMetadataMachineReadableCodeObject


if metadataObj.type == AVMetadataObject.ObjectType.qr {
// If the found metadata is equal to the QR code metadata then update the status label's text and set the bounds
let barCodeObject = videoPreviewLayer?.transformedMetadataObject(for: metadataObj)
qrCodeFrameView.frame = barCodeObject!.bounds


print("QR Code: \(metadataObj.stringValue)")
}
}
}

Swift 5它的简单和超级快! !

$(OCTAVE _ EXECUTABLE)

你只需要添加可可豆荚“条形码扫描仪”这里是完整的代码

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '12.0'
target 'Simple BarcodeScanner'
do
pod 'BarcodeScanner'
end
$(OneDrive)

确保在.plist 文件中添加 Camera 权限

<key>NSCameraUsageDescription</key>
<string>Camera usage description</string>
$(OneDriveCommercial)

并以这种方式在 ViewController 中添加 Scanner 和 handle result

import UIKit
import BarcodeScanner


class ViewController: UIViewController, BarcodeScannerCodeDelegate, BarcodeScannerErrorDelegate, BarcodeScannerDismissalDelegate {


override func viewDidLoad() {
super.viewDidLoad()


let viewController = BarcodeScannerViewController()
viewController.codeDelegate = self
viewController.errorDelegate = self
viewController.dismissalDelegate = self


present(viewController, animated: true, completion: nil)
}


func scanner(_ controller: BarcodeScannerViewController, didCaptureCode code: String, type: String) {
print("Product's Bar code is :", code)
controller.dismiss(animated: true, completion: nil)
}


func scanner(_ controller: BarcodeScannerViewController, didReceiveError error: Error) {
print(error)
}


func scannerDidDismiss(_ controller: BarcodeScannerViewController) {
controller.dismiss(animated: true, completion: nil)
}
}
$(操作系统) $(户外)

仍然有任何问题或挑战,请在此查看完整源代码的示例应用程序

$(指定 OutDirWas)

最简单的方法是使用第三方框架和最少的 UI,可以改进

$(输出类型)

您可以简单地使用以下代码(查看关于如何在故事板中创建视图控制器的文档) :

import QRCodeScanner83


guard let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(identifier: "CodeScannerViewController") as? CodeScannerViewController else {
return
}
vc.callbackCodeScanned = { code in
print("SCANNED CODE: \(code)")
vc.dismiss(animated: true, completion: nil)
}
self.present(vc, animated: true, completion: nil)