Skip to content

Instantly share code, notes, and snippets.

@Alex04
Last active January 4, 2023 01:46
Show Gist options
  • Star 51 You must be signed in to star a gist
  • Fork 12 You must be signed in to fork a gist
  • Save Alex04/6976945 to your computer and use it in GitHub Desktop.
Save Alex04/6976945 to your computer and use it in GitHub Desktop.
iPhone QR Code Scanning iOS7
//
// AMScanViewController.h
//
//
// Created by Alexander Mack on 11.10.13.
// Copyright (c) 2013 ama-dev.com. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
@protocol AMScanViewControllerDelegate;
@interface AMScanViewController : UIViewController <AVCaptureMetadataOutputObjectsDelegate>
@property (nonatomic, weak) id<AMScanViewControllerDelegate> delegate;
@property (assign, nonatomic) BOOL touchToFocusEnabled;
- (BOOL) isCameraAvailable;
- (void) startScanning;
- (void) stopScanning;
- (void) setTorch:(BOOL) aStatus;
@end
@protocol AMScanViewControllerDelegate <NSObject>
@optional
- (void) scanViewController:(AMScanViewController *) aCtler didTapToFocusOnPoint:(CGPoint) aPoint;
- (void) scanViewController:(AMScanViewController *) aCtler didSuccessfullyScan:(NSString *) aScannedValue;
@end
//
// AMScanViewController.m
//
//
// Created by Alexander Mack on 11.10.13.
// Copyright (c) 2013 ama-dev.com. All rights reserved.
//
#import "AMScanViewController.h"
@interface AMScanViewController ()
@property (strong, nonatomic) AVCaptureDevice* device;
@property (strong, nonatomic) AVCaptureDeviceInput* input;
@property (strong, nonatomic) AVCaptureMetadataOutput* output;
@property (strong, nonatomic) AVCaptureSession* session;
@property (strong, nonatomic) AVCaptureVideoPreviewLayer* preview;
@end
@implementation AMScanViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)viewWillAppear:(BOOL)animated;
{
[super viewWillAppear:animated];
if(![self isCameraAvailable]) {
[self setupNoCameraView];
}
}
- (void) viewDidAppear:(BOOL)animated;
{
[super viewDidAppear:animated];
}
- (void)viewDidLoad
{
[super viewDidLoad];
if([self isCameraAvailable]) {
[self setupScanner];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)evt
{
if(self.touchToFocusEnabled) {
UITouch *touch=[touches anyObject];
CGPoint pt= [touch locationInView:self.view];
[self focus:pt];
}
}
#pragma mark -
#pragma mark NoCamAvailable
- (void) setupNoCameraView;
{
UILabel *labelNoCam = [[UILabel alloc] init];
labelNoCam.text = @"No Camera available";
labelNoCam.textColor = [UIColor blackColor];
[self.view addSubview:labelNoCam];
[labelNoCam sizeToFit];
labelNoCam.center = self.view.center;
}
- (NSUInteger)supportedInterfaceOrientations;
{
return UIInterfaceOrientationMaskLandscape;
}
- (BOOL)shouldAutorotate;
{
return (UIDeviceOrientationIsLandscape([[UIDevice currentDevice] orientation]));
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation;
{
if([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeLeft) {
AVCaptureConnection *con = self.preview.connection;
con.videoOrientation = AVCaptureVideoOrientationLandscapeRight;
} else {
AVCaptureConnection *con = self.preview.connection;
con.videoOrientation = AVCaptureVideoOrientationLandscapeLeft;
}
}
#pragma mark -
#pragma mark AVFoundationSetup
- (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];
}
#pragma mark -
#pragma mark Helper Methods
- (BOOL) isCameraAvailable;
{
NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
return [videoDevices count] > 0;
}
- (void)startScanning;
{
[self.session startRunning];
}
- (void) stopScanning;
{
[self.session stopRunning];
}
- (void) setTorch:(BOOL) aStatus;
{
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
[device lockForConfiguration:nil];
if ( [device hasTorch] ) {
if ( aStatus ) {
[device setTorchMode:AVCaptureTorchModeOn];
} else {
[device setTorchMode:AVCaptureTorchModeOff];
}
}
[device unlockForConfiguration];
}
- (void) focus:(CGPoint) aPoint;
{
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
if([device isFocusPointOfInterestSupported] &&
[device isFocusModeSupported:AVCaptureFocusModeAutoFocus]) {
CGRect screenRect = [[UIScreen mainScreen] bounds];
double screenWidth = screenRect.size.width;
double screenHeight = screenRect.size.height;
double focus_x = aPoint.x/screenWidth;
double focus_y = aPoint.y/screenHeight;
if([device lockForConfiguration:nil]) {
if([self.delegate respondsToSelector:@selector(scanViewController:didTapToFocusOnPoint:)]) {
[self.delegate scanViewController:self didTapToFocusOnPoint:aPoint];
}
[device setFocusPointOfInterest:CGPointMake(focus_x,focus_y)];
[device setFocusMode:AVCaptureFocusModeAutoFocus];
if ([device isExposureModeSupported:AVCaptureExposureModeAutoExpose]){
[device setExposureMode:AVCaptureExposureModeAutoExpose];
}
[device unlockForConfiguration];
}
}
}
#pragma mark -
#pragma mark AVCaptureMetadataOutputObjectsDelegate
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects
fromConnection:(AVCaptureConnection *)connection
{
for(AVMetadataObject *current in metadataObjects) {
if([current isKindOfClass:[AVMetadataMachineReadableCodeObject class]]) {
if([self.delegate respondsToSelector:@selector(scanViewController:didSuccessfullyScan:)]) {
NSString *scannedValue = [((AVMetadataMachineReadableCodeObject *) current) stringValue];
[self.delegate scanViewController:self didSuccessfullyScan:scannedValue];
}
}
}
}
@end
@jsifalda
Copy link

jsifalda commented Dec 4, 2013

And what about Barcode? Is there simple way how to implement bar codes scanning?

@piersoft
Copy link

perhaps:
@Property (nonatomic, weak) id delegate;
should be: @Property (nonatomic, weak) id delegate;

@lordthistle
Copy link

I receive an error message as soon as I paste the code in XCode.

The error is related to EDScanViewControllerDelegate (.h, line 16): could you please tell me how to correct it? I have very little experience in iOS development.

@Jamonek
Copy link

Jamonek commented Feb 6, 2014

I would also like to know how to fix the error @lordthistle has given.

@gardinergraham
Copy link

The Error in line 16 is EDScanViewControllerDeligate should be AMScanViewControllerDelegate this should then work.
But even so you still need to call the start scan and stop scan as well as display the output. Good luck

@johanneslagos
Copy link

Why are you writing ";" after declaration of methods? Looks like bad syntax.

@RubenVot
Copy link

Very useful. It saved me a lot of time.
Thanks!

@Alex04
Copy link
Author

Alex04 commented Jun 24, 2014

@Jamonek & @lordthistle - I've fixed the issue, the delegate in the header was of wrong type

@danomatika
Copy link

Is "setTourch" a typo? I was expecting it would be "setTorch".

Edit: Also, shouldn't "didTabToFocusOnPoint" be "didTapToFocusOnPoint"?

@Alex04
Copy link
Author

Alex04 commented Jun 25, 2014

thx danomatika -> updated

@danomatika
Copy link

Cool. Thanks again for this! Super useful on my current project.

@danomatika
Copy link

Also, I replaced line 125 in AMScanViewController.m with the following:

if([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeLeft) {
    con.videoOrientation = AVCaptureVideoOrientationLandscapeLeft;
}
else {
    con.videoOrientation = AVCaptureVideoOrientationLandscapeRight;
}

This ensures the preview is in the correct orientation if the app starts in landscape right.

@Alex04
Copy link
Author

Alex04 commented Jul 9, 2014

Have you tried to change the device orientation? If memory serves me right the video orientation might be wrong without adjusting ist properly

@zenghaojim33
Copy link

Hi, can you please tell my how the adjust the camera orientation? It's not properly displaying and I use UIInterfaceOrientationPortrait doesn't work.

@thandang
Copy link

Can it scan data matrix code type? I tried but it can not.

@rascyber
Copy link

Hi, I am getting this error "No known instance method for selector 'respondsToSelector:'

what may be the cause and how to fix this. Thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment