Skip to content

Instantly share code, notes, and snippets.

@Alex04
Last active January 4, 2023 01:46
Show Gist options
  • 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
@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