iOS应用中的QR码扫描

26

我需要在应用程序中集成QR码阅读器,并找到了一个教程

我从这个链接下载了Z-bar sdk。

这是我所做的。

在QRscannerViewController.m文件中:

-(IBAction)StartScan:(id) sender
{
    ZBarReaderViewController *reader = [ZBarReaderViewController new];
     reader.readerDelegate = self;

     reader.readerView.torchMode = 0;

    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];

     // present and release the controller
     [self presentModalViewController: reader
       animated: YES];
     [reader release];

    resultTextView.hidden=NO;
 }

 - (void) readerControllerDidFailToRead: (ZBarReaderController*) reader
                         withRetry: (BOOL) retry{
     NSLog(@"the image picker failing to read");

 }

 - (void) imagePickerController: (UIImagePickerController*) reader didFinishPickingMediaWithInfo: (NSDictionary*) info
 {


     NSLog(@"the image picker is calling successfully %@",info);
      // ADD: get the decode results
     id<NSFastEnumeration> results = [info objectForKey: ZBarReaderControllerResults];
     ZBarSymbol *symbol = nil;
     NSString *hiddenData;
      for(symbol in results)
       hiddenData=[NSString stringWithString:symbol.data];
      NSLog(@"the symbols  is the following %@",symbol.data);
      // EXAMPLE: just grab the first barcode
     //  break;

      // EXAMPLE: do something useful with the barcode data
      //resultText.text = symbol.data;
      resultTextView.text=symbol.data;


       NSLog(@"BARCODE= %@",symbol.data);

      NSUserDefaults *storeData=[NSUserDefaults standardUserDefaults];
      [storeData setObject:hiddenData forKey:@"CONSUMERID"];
      NSLog(@"SYMBOL : %@",hiddenData);
      resultTextView.text=hiddenData;
     [reader dismissModalViewControllerAnimated: NO];

 }

所有必要的框架都已添加,因此不会出现“引用自”错误。

当我点击扫描按钮时,ZBarReaderViewController正常显示,我按住alt键并左键单击鼠标以打开模拟器的照片库,一切都正常。

问题在于:

  1. QR图像未被扫描,即imagePickerController:(UIImagePickerController*) reader didFinishPickingMediaWithInfo函数未被调用。
  2. QR图像显示比其原始大小大。

enter image description here

如何解决这个问题?

为什么图像没有被扫描?


1
QR码应该完全可见才能读取。由于QR码图像较大,库无法扫描..图像中应该有所有四个角。 - Sharon Nathaniel
@SharonNathaniel,如何减小那个大小? - Nazik
1
建议在真实设备上尝试,将其指向纸张或屏幕上的 QR 码。由于您在模拟器中从照片库中获取图像,我不确定您能否在将其提供给读者之前对其进行操作。我建议在设备上尝试。 - Sharon Nathaniel
5个回答

87

随着 iOS7 的发布,您不再需要使用外部框架或库。现在,iOS生态系统通过AVFoundation完全支持扫描从QR、EAN到UPC的几乎所有代码。

只需查看技术说明AVFoundation编程指南AVMetadataObjectTypeQRCode是您的好伙伴。

这里有一个很好的教程,它一步一步地演示了如何使用:

iPhone QR code scan library iOS7

这里是一个关于如何设置它的小例子:

#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];

    [self.session startRunning];

}

5
这应该是新答案!在SO网站上,答案能否更改? - Tamby Kojak
3
不要忘记在AVCaptureSession上调用-startRunning方法。请参阅此处的文档 - Pang
回答中的域名链接www.ama-dev.com已失效。 - Pang
@Pang 谢谢,很惊讶 OP 没有提到这一点,我已经将其编辑到他的答案中,现在它是一个完全功能的开箱即用解决方案。 - Albert Renshaw

28

我们的 iPhone 应用程序中使用 ZBar SDK 进行 BR 和 QR 码扫描。

您可以找到逐步说明以及示例代码的文章。

如何在 iPhone 上使用条形码扫描器 (BR 和 QR) 教程(使用 ZBar)

看看它是如何工作的:

  1. 这里下载 ZBar SDK。

  2. 在您的项目中添加以下框架:

    • AVFoundation.framework
    • CoreGraphics.framework
    • CoreMedia.framework
    • CoreAudio.framework
    • CoreVideo.framework
    • QuartzCore.framework
    • libiconv.dylib
  3. 将下载的库libzbar.a添加到框架中。

  4. 在您的类中导入头文件并确认它的委托:

    #import "ZBarSDK.h"

然后

@interface ViewController : UIViewController <ZBarReaderDelegate>

5.扫描图像

- (IBAction)startScanning:(id)sender {

    NSLog(@"Scanning..");    
    resultTextView.text = @"Scanning..";

    ZBarReaderViewController *codeReader = [ZBarReaderViewController new];
    codeReader.readerDelegate=self;
    codeReader.supportedOrientationsMask = ZBarOrientationMaskAll;

    ZBarImageScanner *scanner = codeReader.scanner;
    [scanner setSymbology: ZBAR_I25 config: ZBAR_CFG_ENABLE to: 0];

    [self presentViewController:codeReader animated:YES completion:nil];    

}

6. 获得结果在

- (void) imagePickerController: (UIImagePickerController*) reader didFinishPickingMediaWithInfo: (NSDictionary*) info
{
    //  get the decode results
    id<NSFastEnumeration> results = [info objectForKey: ZBarReaderControllerResults];

    ZBarSymbol *symbol = nil;
    for(symbol in results)
        // just grab the first barcode
        break;

    // showing the result on textview
    resultTextView.text = symbol.data;    

    resultImageView.image = [info objectForKey: UIImagePickerControllerOriginalImage];

    // dismiss the controller 
    [reader dismissViewControllerAnimated:YES completion:nil];
}
希望这可以帮助你,如果在这个例子中遇到任何问题,请告诉我,很乐意帮忙。 官方文档

1
+1,很棒的教程,它能在模拟器上运行吗?还是我需要在设备上测试一下? - Nazik
1
@NAZIK,非常高兴听到它对你有帮助 :)是的,每当我学到新知识时,我会继续分享。 - swiftBoy
错误:ld:文件是通用的(3个片段),但不包含armv7s片段:proejctPath/libzbar.a文件“proejctPath/libzbar.a”适用于架构armv7s clang:错误:链接器命令失败,退出代码为1(使用-v查看调用) - Solid Soft
@Jagdish,你能否请检查一下这个链接(https://dev59.com/cGjWa4cB1Zd3GeqPs66x),并让我知道你是否还有问题?顺便问一下,我想知道你是否更新了XCode或者不小心错过了构建设置。 - swiftBoy
2
@Ramdhan Choudhary 我已经解决了这个问题,从这里下载新的ZBar SDK:http://sourceforge.net/projects/zbar/files/iPhoneSDK/beta/ZBarSDK-1.3.1.dmg/download,并将其替换为您的包即可。感谢详细的答案,让我点个赞... - Solid Soft
显示剩余5条评论

9

请在iOS 7及以上版本中尝试此操作。

捕获二维码的方法如下:

- (IBAction)Capture:(id)sender {

    isFirst=true;
    _session = [[AVCaptureSession alloc] init];
    _device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    NSError *error = nil;

    _input = [AVCaptureDeviceInput deviceInputWithDevice:_device error:&error];
    if (_input) {
        [_session addInput:_input];
    } else {
        NSLog(@"Error: %@", error);
    }

    _output = [[AVCaptureMetadataOutput alloc] init];
    [_output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    [_session addOutput:_output];

    _output.metadataObjectTypes = [_output availableMetadataObjectTypes];

    _prevLayer = [AVCaptureVideoPreviewLayer layerWithSession:_session];
    _prevLayer.frame = self.view.bounds;
    _prevLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    [self.view.layer addSublayer:_prevLayer];

    [_session startRunning];
}

要进行阅读,使用代理方法:

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
    CGRect highlightViewRect = CGRectZero;
    AVMetadataMachineReadableCodeObject *barCodeObject;
    NSString *detectionString = nil;
    NSArray *barCodeTypes = @[AVMetadataObjectTypeUPCECode, AVMetadataObjectTypeCode39Code, AVMetadataObjectTypeCode39Mod43Code,
            AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode93Code, AVMetadataObjectTypeCode128Code,
            AVMetadataObjectTypePDF417Code, AVMetadataObjectTypeQRCode, AVMetadataObjectTypeAztecCode];

    for (AVMetadataObject *metadata in metadataObjects) {
        for (NSString *type in barCodeTypes) {
            if ([metadata.type isEqualToString:type])
            {
                barCodeObject = (AVMetadataMachineReadableCodeObject *)[_prevLayer transformedMetadataObjectForMetadataObject:(AVMetadataMachineReadableCodeObject *)metadata];
                highlightViewRect = barCodeObject.bounds;
                detectionString = [(AVMetadataMachineReadableCodeObject *)metadata stringValue];
                break;
            }
        }

        if (detectionString != nil)
        {
            if (isFirst) {
            isFirst=false;
            _label.text = detectionString;
            break;
           }
        }
        else
            _label.text = @"(none)";
    }

    _highlightView.frame = highlightViewRect;
}

我的二维码被扫描了多次,如何解决?当我尝试只扫描一次时,实际上在获取值后会弹出一个警告视图,然后它会移动到另一页,有时会获取4次值,出现4个警告视图和4次跳转。 - Akshay

4

首先从这里导入ZXingWidget库

尝试一下,

- (IBAction)btnScanClicked:(id)sender {

    ZXingWidgetController *widController = [[ZXingWidgetController alloc] initWithDelegate:self showCancel:YES OneDMode:NO];
    QRCodeReader* qrcodeReader = [[QRCodeReader alloc] init];
    NSSet *readers = [[NSSet alloc ] initWithObjects:qrcodeReader,nil];
    [qrcodeReader release];
    widController.readers = readers;
    [readers release];
    NSBundle *mainBundle = [NSBundle mainBundle];
    widController.soundToPlay =
    [NSURL fileURLWithPath:[mainBundle pathForResource:@"beep-beep" ofType:@"aiff"] isDirectory:NO];
    [self presentModalViewController:widController animated:YES];
    [widController release];


}

和委托

- (void)zxingController:(ZXingWidgetController*)controller didScanResult:(NSString *)result {

}

需要使用哪个SDK,在zxing中?在哪里下载? - Nazik

2
你可以使用我的框架来进行QRCodeReader

https://www.cocoacontrols.com/controls/qrcodereader

如何使用

  1. 嵌入二进制文件
  2. 将UIView拖放到您的视图控制器中。
  3. 更改UIVIew的类。
  4. 绑定您的UIView。

在您的视图控制器(即“ViewController.m”)中粘贴“M1,M2”方法

“M1”viewDidLoad


- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    self.title = @"QR Code Reader";
    [qrCodeView setDelegate:self];
    [qrCodeView startReading];
}

这里是代理方法: "M2" QRCodeReaderDelegate


#pragma mark - QRCodeReaderDelegate
- (void)getQRCodeData:(id)qRCodeData {
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"QR Code" message:qRCodeData preferredStyle:UIAlertControllerStyleAlert];

    UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Close" style:UIAlertActionStyleDefault handler:nil];
    [alertController addAction:cancel];

    UIAlertAction *reScan = [UIAlertAction actionWithTitle:@"Rescan" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        [qrCodeView startReading];
    }];
    [alertController addAction:reScan];
    [self presentViewController:alertController animated:YES completion:nil];
}

谢谢。


我正在使用Xcode 7.3.1和Swift 2,其中一个Pod无法运行时会产生错误的lib文件。有人能建议我该使用哪个Pod / lib吗? - Mubashar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接