Monday, March 11, 2013

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


What's up 01000101 developers!!

Sitting on Rolling-Chair, Looking for good resources "How to use BarCode scanner in iPhone
".. on IT's Lord Google  and digging on StackOverFlow.. but still not sure How to implement Bar Code Scanner.

Okay just chill you are landed up here and I bet, after 20 minutes you will have your own application for Scanning bar codes :)



So stay with me, and do it step by step by .. don't forget to drop me a message or comment.

At the end of this Tutorial you can find Complete Source code zip file.

What is BarCode?
There are two types of code scanner

1. BR Code (Bar Code / 1D)
Google says "A machine-readable code in the form of numbers and a pattern of parallel lines of varying widths, printed on and identifying a product."



2. QR Code (Quick Response Code / 2D)
A QR Code is a matrix barcode (or two-dimensional code), readable by QR scanners, mobile phones with a camera, and smartphones.



So we are going to use ZBar SDK for BR and QR code scanning in our iPhone application.

Note : This Application Developed Using : iOS 6 , Xcode 4.6, and MAC OS X Lion 10.8.1

PHASE - I (Create New Project)

So, Let's Fire Xcode!!

Go to File --> New --> Project

Now we can see a Pop up Window for selecting our application templet 

So make sure you Single View Application templet as shown in below picture and Go for Next..



In the Next Window we need to put Our Project Details this way

 -----------------------------------------------------------------
| Product Name : BarCodeScannerDemo    |
| Organization Name :RDCWorld                   |
| Company Identifier : com.rdcworld              |
|                                                                                  |
| Class Prefix :  (leave it blank for now)         |
|                                                                                  |
| Devices : iPhone                                          |
 ----------------------------------------------------------------

Note : Don't forget to Make Tick mark on "Use Automatic Reference Counting" option.



Go to Next --> Create.

Now you can see Xcode default dashboard with our newly created project .

PHASE - II (Add Extra Frameworks/ Lib )

to use the ZBar Scanner we need to add ZBar SDK to our Project.


1. Download ZBar SDK I have uploaded zip file here also you can find latest SDK dmg file from official website here.

2. Extract downloaded stuff, you can find ZBarSDK named folder inside it (which contains headers and resources files).

3. Drag the ZBarSDK folder into your Xcode project, Make sure that the “Copy Items into destination group’s folder” checkbox is checked.

4. Now Select project (Blue Icon) go to --> Build Phases -->  Link Binary With Libraries.
Click the + and add each of these seven frameworks.

  • AVFoundation.framework
  • CoreGraphics.framework
  • CoreMedia.framework
  • CoreAudio.framework
  • CoreVideo.framework
  • QuartzCore.framework
  • libiconv.dylib


sometimes the order is important, you can see libzbar.a is at the bottom (it added auto when we dragged SDK)



Now you can arrange the project structure as shown below.



PHASE - III (Design UI)

Open ViewController.xib file

1. drag UIImage View from object lib and resize it as given screen shot
2. add one UILabel just below to ImageView and double click on it and put "Scan Result is :"
3. now drag UITextView and resize it like ImageView, double click and write "No bar code scanned.."
4. finally add one UIButton view and give it name as "Scan"



PHASE - IV (Create IBOutlets and IBAction )

We are going to create IBOutlet for UIImageView and UILabel and IBAction methods for UIButton .
So just open ViewController.xib

Okay, Now select Assistant Editor on Top Right side



You can see our ViewController.xib (Left side) + ViewController.h (Right side) opened together.

Create IBOutlet

1. select ImageView -- > press Ctrl +Click and drag cursor  between @interface and @end  (in Right side Header File).



2. in the pop up window, put name as "resultImageView" and connect.



you can see below line is added in ViewController.h file

@property (weak, nonatomic) IBOutlet UIImageView *resultImageView;

do the same for UITextView and give name as "resultTextView"

below line will added in header file

@property (weak, nonatomic) IBOutlet UITextView *resultTextView;

Create IBAction

3.  select Scan Button and Ctrl +Click and drag Cursor below to to IBOutlets created.

4. in the pop up window make sure you change Connection type Outlet to --> Action, and give method name as "startScanning"



you will find one IBAction method is created in header file and empty body is added in implementation file (.m file ) too

- (IBAction)startScanning:(id)sender;


Done!! now back to Standard Editor




PHASE - V (Writing Code)


~ ~ ~ ~ ~ ~ ~ ~ ~              Controller Class (ViewController)           ~ ~ ~ ~ ~ ~ ~ ~ ~   

Open ViewController.h file

1. add #import  statement

#import "ZBarSDK.h"

2. add ZBar Delegate, we are going to use its delegates methods

@interface ViewController : UIViewController <ZBarReaderDelegate>

So Finally our ViewController.h file look like

-----------------------------------------------------------------------------------------------------------------------------------------
//
//  ViewController.h
//  BarCodeScannerDemo
//
//  Created by RDC on 3/11/13.
//  Copyright (c) 2013 RDC World. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "ZBarSDK.h"

@interface ViewController : UIViewController<ZBarReaderDelegate>

@property (weak, nonatomic) IBOutlet UIImageView *resultImageView;
@property (weak, nonatomic) IBOutlet UITextView *resultTextView;

- (IBAction)startScanning:(id)sender;

@end
-----------------------------------------------------------------------------------------------------------------------------------------

now open ContactObject's implementation class ViewController.m

1.  add synthesize (for all declared variable in header file with @property) just below to @implementation

@synthesize resultImageView;
@synthesize resultTextView;

2. Now Here is application's Heart, update startScanning method body this way

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

3. Implement ZBar's Delegate method

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

That's it, Save file.

So Finally our ViewController.m file look like

-----------------------------------------------------------------------------------------------------------------------------------------
//
//  ViewController.m
//  BarCodeScannerDemo
//
//  Created by RDC on 3/11/13.
//  Copyright (c) 2013 RDC World. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()
@end

@implementation ViewController

@synthesize resultImageView;
@synthesize resultTextView;

#pragma mark - ViewController's LifeCycle methods

- (void)viewDidLoad
{
    [super viewDidLoad];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];    
}

#pragma mark - Button click method

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

#pragma mark - ZBar's Delegate method

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

@end
-----------------------------------------------------------------------------------------------------------------------------------------


~ ~ ~ ~ ~ ~ ~ ~ ~              Application Delegate Class (AppDelegate)          ~ ~ ~ ~ ~ ~ ~ ~ ~  

Make sure your AppDelegate file code should be default

Finally our AppDelegate.h file look like

-----------------------------------------------------------------------------------------------------------------------------------------
//
//  AppDelegate.h
//  BarCodeScannerDemo
//
//  Created by RDC on 3/11/13.
//  Copyright (c) 2013 RDC World. All rights reserved.
//

#import <UIKit/UIKit.h>

@class ViewController;

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@property (strong, nonatomic) ViewController *viewController;

@end
-----------------------------------------------------------------------------------------------------------------------------------------


Finally our AppDelegate.m file look like

-----------------------------------------------------------------------------------------------------------------------------------------
//
//  AppDelegate.m
//  BarCodeScannerDemo
//
//  Created by RDC on 3/11/13.
//  Copyright (c) 2013 RDC World. All rights reserved.
//

#import "AppDelegate.h"
#import "ViewController.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];    
    self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];
    return YES;
}

//for now leave rest all empty methods..

@end
-----------------------------------------------------------------------------------------------------------------------------------------

Okay wrap it up this application. let's Run it.

1. for BR Code

click on Scan Button --> Look for any Book have BarCode or you can create Barcode online here -- > zoom on it.



2. for QR code

same way click on Button --> create your QR code online here --> zoom on it --> see the result.
Note : when it successfully read the  code you can see Green Frame.



Wow!! we did it. and Credit goes to you.. just before Half an hour you started it now you can write any app for scanning Bar codes in iOS.

You can find complete project source code zip file here : BarCodeScannerDemo.zip (2.69 MB)


I Would love to here your thoughts !!

5 comments:

  1. Hi RDC,
    you have explained the example step by step..its really gr8:)..
    I have one issue.I have implemented all the steps,and trying out with the simulator .
    I did the following steps:
    1.clicked scan button,the image selection screen appears saying "camera simulation tap and hold with two fingers to select the image"
    2.did the alt+left click [in simulator] to launch the photos app.
    3.selected the QR IMAGE which is previously saved

    The issue is the app is in the same screen showing the selected QR image and scan is not happening.
    I guess the delegate method "imagePickerController:(UIImagePickerController *)reader didFinishPickingMediaWithInfo:(NSDictionary *)info" is not called.

    Please guide as what should be done.

    ReplyDelete
  2. Hi,
    This is a handy tutorial. Thank you for offering a demo as well. Just one quick question. How to perform the result directly to the website instead of just show the url on the screen?

    ReplyDelete
  3. Hello,
    This is an excellent tutorial. Got things working while waiting for car repair.
    One thing to add: A program probably wants to do something with the result besides showing the picture and the text. Closing the screen was not obvious.
    One thing to change: I would think that the delegate method would be called in all cases (i.e. including Cancel). Since a dictionary is being passed, it would be easy to include a Cancel option. Just a thought.
    Again, thanks. Great job.

    ReplyDelete
  4. Hi,
    This tutorial is great and very helpful,
    but i would like to ask if possible to remove the toolbar?
    please help me this.
    thanks in advanced.

    -Mark;

    ReplyDelete
  5. Extremely helpful, thanks! It's always nice to read a tutorial complete with pictures, they work so much better for me. It looks like smartphone scanning is part of the future, so I need to keep up on how to do it.

    Jenn | http://www.manateeworks.com

    ReplyDelete