前言:一个简单扫描功能集成。
大致步骤:
1、检查是否有无权限访问相机;
2、如果有,初始化相机、扫描器
2.1、获取摄像设备;
2.2、创建输入流;
2.3、创建输出流;
2.4、设置代理,在主线程刷新;
2.5、设置敏感区域;
2.6、初始化连接对象;
2.7、高质量采集率;
2.8、设置条形码类型;
2.9、更新页面
代码如下:
#import "IWScanViewController.h"
#import "IWScanMaskView.h"
#import <AVFoundation/AVFoundation.h>
//扫描线的
static const CGFloat KLineX = 20;
static const CGFloat KLineY = 20;
static const CGFloat KLineH = 2;
@interface IWScanViewController ()<AVCaptureMetadataOutputObjectsDelegate>
{
AVCaptureDevice *_device;
AVCaptureInput *_input;
AVCaptureMetadataOutput *_output;
AVCaptureSession *_session;
AVCaptureVideoPreviewLayer *_preview;
NSTimer *_timer;
UIImageView *_line;
BOOL _upOrdown;
int _num;
}
@end
@implementation IWScanViewController
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (_session && ![_session isRunning]) {
[_session startRunning];
_timer = [NSTimer scheduledTimerWithTimeInterval:.02 target:self selector:@selector(animation) userInfo:nil repeats:YES];
}
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[_timer invalidate];
_timer = nil;
}
- (void)viewDidLoad {
[super viewDidLoad];
//1.设置标题
self.title = @"扫一扫";
//2.检验是否有无权限访问相机
[self checkAVAuthorizationStatus];
}
#pragma mark 检验是否有无权限访问相机
- (void)checkAVAuthorizationStatus
{
AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
if (status == AVAuthorizationStatusAuthorized || status == AVAuthorizationStatusNotDetermined) {
[self setupCamera];
}else{
[SVProgressHUD showErrorWithStatus:@"您没有权限访问相机"];
}
}
#pragma mark 初始化相机,扫描器
- (void)setupCamera
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//获取摄像设备
_device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
//创建输入流
_input = [[AVCaptureDeviceInput alloc] initWithDevice:_device error:nil];
//创建输出流
_output = [[AVCaptureMetadataOutput alloc] init];
//设置代理,在主线程里刷新
[_output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
//设置敏感区域
CGFloat outputH = KScreenHeight;
CGFloat outputW = KScreenWidth;
[_output setRectOfInterest:CGRectMake((outputH - KScanHeight)/2/outputH, KScanX/outputW, KScanHeight/outputH, (outputW - 2*KScanX)/outputW)];
//初始化连接对象
_session = [[AVCaptureSession alloc] init];
//高质量采集率
[_session setSessionPreset:AVCaptureSessionPresetHigh];
if ([_session canAddInput:_input]) {
[_session addInput:_input];
}
if ([_session canAddOutput:_output]) {
[_session addOutput:_output];
}
//条形码类型
if ([_output.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeQRCode]) {
_output.metadataObjectTypes = [NSArray arrayWithObjects:AVMetadataObjectTypeCode128Code,AVMetadataObjectTypeUPCECode,AVMetadataObjectTypeCode39Code,AVMetadataObjectTypeCode39Mod43Code,AVMetadataObjectTypeEAN13Code,AVMetadataObjectTypeEAN8Code,AVMetadataObjectTypeCode93Code,AVMetadataObjectTypePDF417Code,AVMetadataObjectTypeQRCode,AVMetadataObjectTypeAztecCode,AVMetadataObjectTypeInterleaved2of5Code,AVMetadataObjectTypeITF14Code,AVMetadataObjectTypeDataMatrixCode,nil];
}
dispatch_async(dispatch_get_main_queue(), ^{
//更新界面
_preview = [AVCaptureVideoPreviewLayer layerWithSession:_session];
_preview.videoGravity = AVLayerVideoGravityResizeAspectFill;
_preview.frame = self.view.layer.bounds;
[self.view.layer insertSublayer:_preview atIndex:0];
[_session startRunning];
[self lineAnimation];
});
});
}
#pragma mark 添加条形线
- (void)lineAnimation{
IWScanMaskView *scanMaskView = [[IWScanMaskView alloc] initWithFrame:_preview.frame];
[self.view addSubview:scanMaskView];
UIImageView * image = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"home_scan_frame"]];
image.frame = CGRectMake(KScanX, (KScreenHeight - KScanHeight)/2, KScreenWidth - 2*KScanX, KScanHeight);
[self.view addSubview:image];
UILabel *pointOutLable = [[UILabel alloc] init];
CGFloat pointOutLableH = 20;
CGFloat pointOutLableY = CGRectGetMaxY(image.frame) + pointOutLableH;
pointOutLable.frame = CGRectMake(0, pointOutLableY, KScreenWidth, pointOutLableH);
pointOutLable.font = [UIFont systemFontOfSize:13.0f];
pointOutLable.textAlignment = NSTextAlignmentCenter;
pointOutLable.textColor = [UIColor whiteColor];
pointOutLable.text = @"将二维码放入框内,即可自动扫描";
[self.view addSubview:pointOutLable];
CGFloat lineW = image.frame.size.width - 2*KLineX;
_line = [[UIImageView alloc] initWithFrame:CGRectMake(KLineX, KLineY, lineW, KLineH)];
_line.image = [UIImage imageNamed:@"home_scan_line"];
[image addSubview:_line];
//定时器
_timer = [NSTimer scheduledTimerWithTimeInterval:.02 target:self selector:@selector(animation) userInfo:nil repeats:YES];
}
-(void)animation{
if (_upOrdown == NO) {
_num ++;
_line.frame = (CGRect){{KLineX, KLineY + KLineH*_num},_line.frame.size};
if (KLineH*_num == (KScanHeight - 2*KLineY)) {
_upOrdown = YES;
}
}
else {
_num --;
_line.frame = (CGRect){{KLineX, KLineY + KLineH*_num},_line.frame.size};
if (_num == 0) {
_upOrdown = NO;
}
}
}
#pragma mark - 扫描结果处理
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
NSString *stringValue;
if ([metadataObjects count] > 0) {
AVMetadataMachineReadableCodeObject *metadataObject = [metadataObjects objectAtIndex:0];
if ([metadataObject isKindOfClass:[AVMetadataMachineReadableCodeObject class]]) {
stringValue = [metadataObject stringValue];
}
}
[_session stopRunning];
[_timer setFireDate:[NSDate distantFuture]];
NSLog(@"stringValue is %@",stringValue);
//打开内容需要在此处进行处理
}
@end
#import <UIKit/UIKit.h>
extern const CGFloat KScanHeight;
extern const CGFloat KScanX;
@interface IWScanMaskView : UIView
@end
#import "IWScanMaskView.h"
const CGFloat KScanHeight = 280;
const CGFloat KScanX = 20;
@implementation IWScanMaskView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor clearColor];
}
return self;
}
- (void)drawRect:(CGRect)rect{
self.backgroundColor = [UIColor clearColor];
CGFloat width = self.bounds.size.width;
CGFloat height = self.bounds.size.height;
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGRect screenDrawRect = self.bounds;
CGRect clearDrawRect = CGRectMake(KScanX, (height - KScanHeight)/2, width - 2*KScanX, KScanHeight);
CGContextSetRGBFillColor(ctx, 0 / 255.0,0 / 255.0,0 / 255.0,0.5);
CGContextFillRect(ctx, screenDrawRect);
CGContextClearRect(ctx, clearDrawRect);
}
@end