这篇文章主要是参考了博主 WestLC 的《 iOS 原生二维码扫描(可限制扫描区域)》 。但是做了一点点的个性化。
整个代码的工作流程是这样的:
运行APP,显示一个蓝色的二维码扫描按钮 ----- 点击蓝色按钮 ----- 开始二维码扫描 ----- 扫描结束 ----- 显示扫描结果 ;然后显示按钮 可循环操作。
---点击按钮---》 这是扫描成功后的显示结果。这个是CSDN的二维码。
#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>
@interface ViewController ()<AVCaptureMetadataOutputObjectsDelegate>
@property (nonatomic,strong)AVCaptureDevice *device;
@property (nonatomic,strong)AVCaptureDeviceInput *input;
@property (nonatomic,strong)AVCaptureMetadataOutput *output;
@property (nonatomic,strong)AVCaptureSession *session;
@property (nonatomic,strong)AVCaptureVideoPreviewLayer *preview;
@property (weak, nonatomic) IBOutlet UIButton *button;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.button.selected = NO;
[self setAVFoundation];
// Do any additional setup after loading the view, typically from a nib.
}
/**
* 按钮点击事件
*
* @param sender sender description
*/
- (IBAction)buttonClick:(id)sender {
//按钮的selected取反
self.button.selected = !self.button.selected;
//凯斯二维码扫描
if (self.button.selected == YES) {
//开始二维码扫描
[self.session startRunning];
//按钮UI移动到二维码扫描后面
[self.view sendSubviewToBack:self.button];
//移除UILabel控件
UILabel *oldLabel = (UILabel *)[self.view viewWithTag:100];
[oldLabel removeFromSuperview];
}
}
/**
* 设置一个UILabel控件 显示扫描结果
*
* @param text 需要显示的数据
*/
- (void)setLabel:(NSString *)text{
UILabel *oldLabel = (UILabel *)[self.view viewWithTag:100];
[oldLabel removeFromSuperview];
UILabel *urlLabel = [[UILabel alloc] init];
urlLabel.frame = CGRectMake(0, 400, 320, 80);
urlLabel.text = text;
urlLabel.textColor = [UIColor redColor];
urlLabel.textAlignment = NSTextAlignmentCenter;
urlLabel.numberOfLines = 0;
urlLabel.tag = 100;
[self.view addSubview:urlLabel];
}
/**
* 设置二维码扫描相关代码
*/
- (void)setAVFoundation{
//设置相机设备
self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
//设置输入源是摄像头
self.input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];
//构建一个输出对象
self.output = [[AVCaptureMetadataOutput alloc] init];
//设置代理
[self.output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
//构建一个session对象
self.session = [[AVCaptureSession alloc] init];
[self.session setSessionPreset:AVCaptureSessionPresetHigh];
//输入和输出的桥接
if ([self.session canAddInput:self.input]) {
[self.session addInput:self.input];
}
if ([self.session canAddOutput:self.output]) {
[self.session addOutput:self.output];
}
//支持二维码和条形码扫描<p style="margin-top: 0px; margin-bottom: 0px;"><span style="white-space: pre;"> </span>self.output.metadataObjectTypes = @[AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code];</p> self.preview = [AVCaptureVideoPreviewLayer layerWithSession:self.session];
self.preview.videoGravity = AVLayerVideoGravityResizeAspectFill;
self.preview.frame = self.view.bounds;
[self.view.layer insertSublayer:self.preview atIndex:0];
}
/**
* 实现AVCaptureMetadataOutputObjectsDelegate代理方法
*
* @param captureOutput captureOutput description
* @param metadataObjects metadataObjects description
* @param connection connection description
*/
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{
NSString *stringVaule;
//扫描成功
if (metadataObjects.count >0) {
//停止扫描
[self.session stopRunning];
//获取扫描结果
AVMetadataMachineReadableCodeObject *metadataObject = [metadataObjects objectAtIndex:0];
stringVaule = metadataObject.stringValue;
NSLog(@"stringVaule = %@",stringVaule);
//把按钮移最上层
[self.view bringSubviewToFront:self.button];
self.button.selected = NO;
//设置UILabel的显示
[self setLabel:stringVaule];
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
实际操作起来还不算复杂,但是有些需要注意的:如设置扫描区域,这个也是博主 WestLC 的一个纠结点,我就是站在他的肩膀上完成了这个例子。
关于AVCapture的编程请移步这里 传送门 。
最后贴上例子的下载链接,请点击我。
下面是条形码的扫描图片: