26

I need to integrate QR-code reader in app and found a tutorial for it.

I downloaded Z-bar sdk from this link.

Here is what I had done.

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

 }

All needed frameworks were added, so there is no referenced from errors.

When I click the scan button, the ZBarReaderViewController appears well and I hold the alt key and left click the mouse to open the photo library of simulator and all works fine.

What the problem is,

  1. The QR image is not get scanned, ie imagePickerController: (UIImagePickerController*) reader didFinishPickingMediaWithInfo function is not get called.
  2. The QR image appears larger than its original size.

enter image description here

How to solve this?

Why the image not get scanned?

Nazik
  • 8,696
  • 27
  • 77
  • 123
  • 1
    qr should be fully visible to read. due to larger image of the qr code the library is unable to scan .. all the four corners should be there in the image. – Sharon Nathaniel Apr 23 '13 at 10:17
  • @SharonNathaniel, how to reduce that size? – Nazik Apr 23 '13 at 10:21
  • 1
    I suggest try it on a device pointing it to a qr code on a paper or screen. Since you are fetching images from the photo library in the simulator I am not sure you can manipulate it before giving it to reader. I recommend trying it on a device. – Sharon Nathaniel Apr 23 '13 at 10:23

5 Answers5

87

As with the release of iOS7 you no longer need to use an external framework or library. The iOS ecosystem with AVFoundation now fully supports scanning almost every code from QR over EAN to UPC.

Just have a look at the Tech Note and the AVFoundation programming guide. AVMetadataObjectTypeQRCode is your friend.

Here is a nice tutorial which shows it step by step: iPhone QR code scan library iOS7

Just a little example on how to set it up:

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

}
Albert Renshaw
  • 17,282
  • 18
  • 107
  • 195
Alexander
  • 7,178
  • 8
  • 45
  • 75
  • 5
    This needs to be the new answer! Can answers change on SO? – Tamby Kojak Jul 02 '14 at 13:07
  • 3
    Don't forget to call `-startRunning` on `AVCaptureSession`. See [documentation here](https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVCaptureSession_Class/index.html). – Pang May 10 '15 at 10:58
  • Link to domain www.ama-dev.com in answer is dead. – Pang Sep 19 '17 at 09:12
  • @Pang Thank you, surprised OP left that out, I've edited it into his answer so that it's now a fully functional solution out-of-the-box. – Albert Renshaw Sep 24 '22 at 19:49
28

use ZBar SDK for BR and QR code scanning in our iPhone application.

you can find step by step article for this, how to do with sample code as well

How to use Barcode Scanner (BR and QR) in iPhone Tutorial (using ZBar)

see how it works

  1. download ZBar SDK from here

  2. add below frameworks in your project

    • AVFoundation.framework
    • CoreGraphics.framework
    • CoreMedia.framework
    • CoreAudio.framework
    • CoreVideo.framework
    • QuartzCore.framework
    • libiconv.dylib
  3. Add the library downloaded libzbar.a of zip in the frameworks

  4. import header in your class and confirm it's delegate

    #import "ZBarSDK.h"

and

@interface ViewController : UIViewController <ZBarReaderDelegate>

5.scan image

- (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.get the result in

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

Hope this will help you, also let me know if you find any trouble in this example, Happy to help

Official Docs

Politta
  • 400
  • 4
  • 10
swiftBoy
  • 35,607
  • 26
  • 136
  • 135
  • 1
    +1, great tutorial, will it work on simulator or I have to test it on device – Nazik Apr 23 '13 at 13:48
  • @NAZIK my pleasure dear, btw I have tested it on Apple Devices only and its working fine, but not sure about Simulator,you can drop me comment if you have any trouble, I can explain whatever I know. – swiftBoy Apr 24 '13 at 04:02
  • Error : ld: file is universal (3 slices) but does not contain a(n) armv7s slice: proejctPath/libzbar.a file 'proejctPath/libzbar.a' for architecture armv7s clang: error: linker command failed with exit code 1 (use -v to see invocation) – Solid Soft Oct 17 '13 at 12:45
  • @Jagdish can you please check [this](http://stackoverflow.com/questions/12518579/clang-error-in-xcode) link, and let me know if you still having trouble btw I'm wondering you may have updated XCode or anyhow missed build settings – swiftBoy Oct 18 '13 at 04:03
  • 2
    @Ramdhan Choudhary I have solved it with download new ZBar SDK from this http://sourceforge.net/projects/zbar/files/iPhoneSDK/beta/ZBarSDK-1.3.1.dmg/download and replace with your package and worked. Also thankful for detailed answer. Let me do +1... – Solid Soft Oct 18 '13 at 05:21
  • @ILikeIOS **I think The project is active and Apache 2.0 licensed..** please read this [**Licensing ZBar SDK Library**](http://zbar.sourceforge.net/iphone/sdkdoc/licensing.html) – swiftBoy Dec 20 '13 at 08:57
9

Try this on iOS 7 and newer.

To capture QR code:

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

To read, use its delegate method:

- (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;
}
Pang
  • 9,564
  • 146
  • 81
  • 122
SM18
  • 718
  • 7
  • 15
  • my qrcodes get scanned many times how to rectify that??when I try to scan one time, actually I have a alert view after getting the value and then it moves to another page and some times it gets value 4 times and 4 alert view comes and 4 times segues happen – Akshay Sep 08 '17 at 03:57
4

FIrst import ZXingWidget library from here.

Try this ,

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


}

and Delegate

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

}
Nazik
  • 8,696
  • 27
  • 77
  • 123
Pratik B
  • 1,599
  • 1
  • 15
  • 32
2

You can use my own framework for QRCodeReader.

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

How to use

  1. Embeded Binaries
  2. Drag and drop UIView in your view controller.
  3. Change Class of UIVIew.
  4. Bind your UIView.

Paste "M1, M2" methods in your view controller (i.e. "ViewController.m")

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

And here the delegate methods: "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];
}

Thanks.

Vivek
  • 4,916
  • 35
  • 40