SoFunction
Updated on 2025-04-12

ios native QR code scanning

To scan the QR code for iOS, there are two third-party libraries to choose from, ZBar and ZXing. What I want to introduce today is the native QR code scanning provided by the AV Foundation framework after iOS7.0.

First, you need to add the framework to "Link Binary With Libraries" in your project build phase, and then you can start.

1. Make preparations and build a UI

The UI effect is shown in the picture

IBOutlet and IBAction are as follows:

@property (weak, nonatomic) IBOutlet UIView *viewPreview;
@property (weak, nonatomic) IBOutlet UILabel *lblStatus;
@property (weak, nonatomic) IBOutlet UIButton *startBtn;
- (IBAction)startStopReading:(id)sender;

The next thing is the code

2. Controller

First import the AVFoundation framework

#import <AVFoundation/>

The controller then implements the AVCaptureMetadataOutputObjectsDelegate protocol

@interface ViewController ()<AVCaptureMetadataOutputObjectsDelegate>

The overall property is as follows:

@property (strong, nonatomic) UIView *boxView;
@property (nonatomic) BOOL isReading;
@property (strong, nonatomic) CALayer *scanLayer;
-(BOOL)startReading;
-(void)stopReading;

//Capture the conversation

@property (nonatomic, strong) AVCaptureSession *captureSession;

//Display layer

@property (nonatomic, strong) AVCaptureVideoPreviewLayer *videoPreviewLayer;

Then initialize in the ViewDidLoad method

- (void)viewDidLoad {
  [super viewDidLoad];

  _captureSession = nil;
   _isReading = NO;
  
}

Next, implement the startReading method (this is the key point)

- (BOOL)startReading {
 NSError *error;
 //1. Initialize the capture device (AVCaptureDevice), type AVMediaTypeVideo AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
 //2. Create input stream with captureDevice AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&amp;error];
 if (!input) {
  NSLog(@"%@", [error localizedDescription]);
  return NO;
 }
 //3. Create media data output stream AVCaptureMetadataOutput *captureMetadataOutput = [[AVCaptureMetadataOutput alloc] init];
 //4. Instantiate the capture session _captureSession = [[AVCaptureSession alloc] init];
 //4.1. Add input stream to session [_captureSession addInput:input];
 //4.2. Add media output stream to session [_captureSession addOutput:captureMetadataOutput];
 //5. Create a serial queue and add media output stream to the queue dispatch_queue_t dispatchQueue;
 dispatchQueue = dispatch_queue_create("myQueue", NULL);
 //5.1. Set up the proxy [captureMetadataOutput setMetadataObjectsDelegate:self queue:dispatchQueue];
 //5.2. Set the output media data type to QRCode [captureMetadataOutput setMetadataObjectTypes:[NSArray arrayWithObject:AVMetadataObjectTypeQRCode]];
 //6. Instantiate the preview layer _videoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_captureSession];
 //7. Set the preview layer filling method [_videoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
 //8. Set the frame of the layer [_videoPreviewLayer setFrame:_viewPreview.];
 //9. Add layer to the layer of the preview view [_viewPreview.layer addSublayer:_videoPreviewLayer];
 //10. Set the scan range  = CGRectMake(0.2f, 0.2f, 0.8f, 0.8f);
 //10.1.Scan the box _boxView = [[UIView alloc] initWithFrame:CGRectMake(_viewPreview. * 0.2f, _viewPreview. * 0.2f, _viewPreview. - _viewPreview. * 0.4f, _viewPreview. - _viewPreview. * 0.4f)];
 _boxView. = [UIColor greenColor].CGColor;
 _boxView. = 1.0f;
 [_viewPreview addSubview:_boxView];
 //10.2.Scan the line _scanLayer = [[CALayer alloc] init];
 _scanLayer.frame = CGRectMake(0, 0, _boxView., 1);
 _scanLayer.backgroundColor = [UIColor brownColor].CGColor;
 [_boxView.layer addSublayer:_scanLayer];
 NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.2f target:self selector:@selector(moveScanLayer:) userInfo:nil repeats:YES];
 [timer fire];

 //10. Start scanning [_captureSession startRunning];
 return YES;
}

Implement the AVCaptureMetadataOutputObjectsDelegate protocol method

#pragma mark - AVCaptureMetadataOutputObjectsDelegate
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
 //Judge whether there is any data if (metadataObjects != nil &amp;&amp; [metadataObjects count] &gt; 0) {
  AVMetadataMachineReadableCodeObject *metadataObj = [metadataObjects objectAtIndex:0];
  //Judge the data type of the return  if ([[metadataObj type] isEqualToString:AVMetadataObjectTypeQRCode]) {
   [_lblStatus performSelectorOnMainThread:@selector(setText:) withObject:[metadataObj stringValue] waitUntilDone:NO];
   [self performSelectorOnMainThread:@selector(stopReading) withObject:nil waitUntilDone:NO];
   _isReading = NO;
  }
 }
}

Implement the timer method moveScanLayer:(NSTimer *)timer

- (void)moveScanLayer:(NSTimer *)timer
{
 CGRect frame = _scanLayer.frame;
 if (_boxView. < _scanLayer.) {
   = 0;
  _scanLayer.frame = frame;
 }else{
   += 5;
  [UIView animateWithDuration:0.1 animations:^{
   _scanLayer.frame = frame;
  }];
 }
}

Implement the start and stop methods

- (IBAction)startStopReading:(id)sender {
  if (!_isReading) {
   if ([self startReading]) {
    [_startBtn setTitle:@"Stop" forState:UIControlStateNormal];
    [_lblStatus setText:@"Scanning for QR Code"];
   }
  }
  else{
   [self stopReading];
   [_startBtn setTitle:@"Start!" forState:UIControlStateNormal];
  }
  _isReading = !_isReading;
}
-(void)stopReading{
 [_captureSession stopRunning];
 _captureSession = nil;
 [_scanLayer removeFromSuperlayer];
 [_videoPreviewLayer removeFromSuperlayer];
}

The above content is the entire content of this article introducing you to the scan of the native QR code of iOS. I hope you like it.