iOS 条形码、二维码心得

来源:互联网 发布:蚁群优化算法 matlab 编辑:程序博客网 时间:2024/06/10 15:45

写这篇文章之前,先说一声抱歉,因为邮箱开发那篇文章已经三个星期没有更新了。因为邮箱开发篇幅较长,并且公司现在工作很多,来不及更新,预计会在五月中旬到六月更新完吧。


简单介绍一下JSScanViewController的几点优势(其实JS就是技术的首字母啦,哈哈。。。)。

  • JSCodeScan能够识别二位码和条形码
  • 界面简单,优雅,清晰
  • 加入了闪光灯功能,扫码不受环境限制
  • 嵌入非常简单,只需两行代码JSScanViewController *sv = [[JSScanViewController alloc] init];
    [self.navigationController pushViewController:sv animated:YES];
  • 扫描结果通过代理回调,结果随便怎么用,随便哪里用
  • JSCodeScan对你的应用做到零侵入,随心所欲,想嵌就嵌,想删就删,丝毫不影响你的应用

首先,我在.h文件声明了两个可选的代理方法,一个是用户点击返回上一级的操作时,会触发–scanViewControllerWillBack:这个方法。另一个是扫描成功时会触发–scanViewController:result:这个方法,供开发者调用。这两个方法就不用说明了吧。

@protocol JSScanViewControllerDelegate <NSObject>@optional/** 扫描成功回调 @param scanVc 扫描控制器本身 @param result 扫描的结果 */-(void)scanViewController:(JSScanViewController *)scanVc result:(NSString *)result;/** 点击返回按钮回调 @param scanVc 扫描控制器本身 */-(void)scanViewControllerWillBack:(JSScanViewController *)scanVc;

.m文件的实现如下

#import "JSScanViewController.h"#import <AVFoundation/AVFoundation.h>#import "ScanAreaView.h"#import "UIView+Extension.h"#define iWidth [UIScreen mainScreen].bounds.size.width#define iHeight [UIScreen mainScreen].bounds.size.height#define margin 3.0#define bottomHeight 100.0typedef enum{    codeType_QRCode,        //二维码    codeType_BarCode,       //条形码}codeType;@interface JSScanViewController ()<AVCaptureMetadataOutputObjectsDelegate, UIAlertViewDelegate>@property(nonatomic, strong) AVCaptureDevice *device;@property(nonatomic, strong) AVCaptureMetadataOutput *output;@property(nonatomic, strong) AVCaptureSession *session;     //输入输出的中间桥梁@property(nonatomic, assign) codeType type;                 //扫描类型@property (strong, nonatomic) UISegmentedControl *segment;@property(nonatomic, strong) ScanAreaView *scanView;        //扫描框@property(nonatomic, assign) CGFloat scanLineY;             //扫描线的Y值@property(nonatomic, strong) UIImageView *scanLine;         //扫描线@property(nonatomic, strong) UIImageView *maskLayer;        //遮罩层@property(nonatomic, strong) UIButton *lightBtn;            //闪光灯按钮@end@implementation JSScanViewController-(UISegmentedControl *)segment{    if (_segment == nil) {        _segment = [[UISegmentedControl alloc] initWithFrame:CGRectMake(30, iHeight-70, iWidth-60, 41)];        [_segment insertSegmentWithTitle:@"条形码" atIndex:0 animated:YES];        [_segment insertSegmentWithTitle:@"二维码" atIndex:1 animated:YES];        [_segment addTarget:self action:@selector(switchType:) forControlEvents:UIControlEventValueChanged];    }    return _segment;}/** *  切换扫码类型 * *  @param sender 切换控件 */- (void)switchType:(UISegmentedControl *)sender {    if (sender.selectedSegmentIndex == 0) { //条形码        [self barCodeSetting];    }else if (sender.selectedSegmentIndex == 1) {   //二维码        [self QRCodeSetting];    }    [self.scanView setNeedsDisplay];}- (void)viewDidLoad {    [super viewDidLoad];    self.view.backgroundColor = [UIColor whiteColor];    UIButton *backBtn = [[UIButton alloc] initWithFrame:CGRectMake(20.0, 20.0, 44.0, 44.0)];    [backBtn setImage:[UIImage imageNamed:@"icon-barcode-back"] forState:UIControlStateNormal];    [backBtn addTarget:self action:@selector(backBtnClick) forControlEvents:UIControlEventTouchUpInside];    [self.view addSubview:backBtn];    UIButton *lightBtn = [[UIButton alloc] initWithFrame:CGRectMake(iWidth-64.0, 20.0, 44.0, 44.0)];    [lightBtn setImage:[UIImage imageNamed:@"icon-flash-off"] forState:UIControlStateNormal];    [lightBtn setImage:[UIImage imageNamed:@"icon-flash-on"] forState:UIControlStateSelected];    [lightBtn addTarget:self action:@selector(lightBtnClick:) forControlEvents:UIControlEventTouchUpInside];    [self.view addSubview:lightBtn];    _lightBtn = lightBtn;    [self.view addSubview:self.segment];    [self.view addSubview:self.maskLayer];    [self.view addSubview:self.scanView];    [self.scanView addSubview:self.scanLine];    self.scanLine.frame = CGRectMake(margin, 0, _scanView.frame.size.width-(2*margin), 1.0);    //获取摄像设备    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];    _device = device;    //创建输入流    AVCaptureDeviceInput * input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];    //创建输出流    AVCaptureMetadataOutput * output = [[AVCaptureMetadataOutput alloc]init];    _output = output;    //    output.rectOfInterest = CGRectMake(0, 0, 1, 1);    //设置代理 在主线程里刷新    [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];    //初始化链接对象    _session = [[AVCaptureSession alloc] init];    //高质量采集率    [_session setSessionPreset:AVCaptureSessionPresetHigh];    [_session addInput:input];    [_session addOutput:output];    AVCaptureVideoPreviewLayer *layer = [AVCaptureVideoPreviewLayer layerWithSession:_session];    layer.videoGravity=AVLayerVideoGravityResizeAspectFill;    layer.frame=CGRectMake(0, 0, iWidth, iHeight-bottomHeight);    [self.view.layer insertSublayer:layer atIndex:0];    [self barCodeSetting];    //开始捕获    [_session startRunning];    CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLink)];    [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];}/** *  返回按钮的点击 */-(void)backBtnClick{    NSLog(@"scanViewControllerWillBack");    if (self.delegate && [self.delegate respondsToSelector:@selector(scanViewControllerWillBack:)])    {        [self.delegate scanViewControllerWillBack:self];    }}/** *  闪关灯按钮的点击 * *  @param btn 闪关灯按钮 */-(void)lightBtnClick:(UIButton *)btn{    btn.selected = !btn.selected;    if ([_device hasTorch] && [_device hasFlash]){        [_device lockForConfiguration:nil];        if (btn.selected) {            [_device setTorchMode:AVCaptureTorchModeOn];            [_device setFlashMode:AVCaptureFlashModeOn];        } else {            [_device setTorchMode:AVCaptureTorchModeOff];            [_device setFlashMode:AVCaptureFlashModeOff];        }        [_device unlockForConfiguration];    }    NSLog(@"lightBtnClick");}-(UIImageView *)maskLayer{    if (_maskLayer == nil)    {        _maskLayer = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, iWidth, iHeight-bottomHeight)];        _maskLayer.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.4];    }    return _maskLayer;}/** *  控制扫描线的位置 */-(void)handleDisplayLink{    self.scanLineY += 1;    if (self.scanLineY> self.scanView.frame.size.height) {        self.scanLineY = 0.0;    }    self.scanLine.y = self.scanLineY;}/** *  扫描结果 */-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{    if (metadataObjects.count>0) {        [_session stopRunning];        _lightBtn.selected = NO;        AVMetadataMachineReadableCodeObject *metadataObject = [metadataObjects objectAtIndex:0];        NSString *result = metadataObject.stringValue;        if (self.delegate && [self.delegate respondsToSelector:@selector(scanViewController:result:)])        {            [self.delegate scanViewController:self result:result];        }        //输出扫描字符串        NSLog(@"扫描结果:%@",result);        NSLog(@"%@", NSStringFromCGRect(_output.rectOfInterest));        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"扫描结果" message:result delegate:self cancelButtonTitle:@"确定" otherButtonTitles: nil];        [alert show];    }}- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{    if (buttonIndex == 0) {        [_session startRunning];    }}/** *  条形码设置 */-(void)barCodeSetting{    self.type = codeType_BarCode;    self.segment.selectedSegmentIndex = 0;    //设置扫码支持的编码格式(条形码)    _output.metadataObjectTypes=@[AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code];    _scanView.frame = [self scanAreaViewFrame];}/** *  二维码设置 */-(void)QRCodeSetting{    self.type = codeType_QRCode;    self.segment.selectedSegmentIndex = 1;    //设置扫码支持的编码格式(二维码)    _output.metadataObjectTypes=@[AVMetadataObjectTypeQRCode];    _scanView.frame = [self scanAreaViewFrame];}-(UIImageView *)scanLine{    if (_scanLine == nil)    {        _scanLine = [[UIImageView alloc] init];        _scanLine.backgroundColor = [UIColor yellowColor];    }    return _scanLine;}-(ScanAreaView *)scanView{    if (_scanView == nil)    {        _scanView = [[ScanAreaView alloc] init];        _scanView.backgroundColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:0.15];        _scanView.frame = [self scanAreaViewFrame];    }    return _scanView;}/** *  设置扫码区域的大小 * *  @return frame */-(CGRect)scanAreaViewFrame{    CGFloat AVCaptureVideoPreviewLayerHeight = iHeight-bottomHeight;    if (self.type == codeType_BarCode) {        CGFloat w = iWidth* 0.8;        CGFloat h = w * 0.3;        CGFloat x = (iWidth-w)*0.5;        CGFloat y = iHeight / 4.0;        self.scanLine.width = w-6.0;        CGFloat outputX = x / iWidth;        CGFloat outputY = y / AVCaptureVideoPreviewLayerHeight;        CGFloat outputW = w / iWidth;        CGFloat outputH = h / AVCaptureVideoPreviewLayerHeight;        //经过测试发现,这个参数里面的x对应的恰恰是距离左上角的垂直距离,y对应的是距离左上角的水平距离。        _output.rectOfInterest = CGRectMake(outputY, outputX, outputH, outputW);        return CGRectMake(x, y, w, h);    }else {        CGFloat w = iWidth* 0.65;        CGFloat h = w;        CGFloat x = (iWidth-w)*0.5;        CGFloat y = iHeight / 4.0;        self.scanLine.width = w-6.0;        CGFloat outputX = x / iWidth;        CGFloat outputY = y / AVCaptureVideoPreviewLayerHeight;        CGFloat outputW = w / iWidth;        CGFloat outputH = h / AVCaptureVideoPreviewLayerHeight;        //经过测试发现,这个参数里面的x对应的恰恰是距离左上角的垂直距离,y对应的是距离左上角的水平距离。        _output.rectOfInterest = CGRectMake(outputY, outputX, outputH, outputW);        return CGRectMake(x, y, w, h);    }}@end

感觉没有什么好说明的,代码里该注释的我已经注释了。
我还是说一下吧,万一真的有人不懂(其实没有必要解释的)。

#import "UIView+Extension.h"

这个类其实就是UI尺寸的一些拓展,比如x,y,width,height,size,center等等的一些东西。

#import "ScanAreaView.h"

ScanAreaView就是draw的扫描界面,具体实现也给你们吧。

@interface ScanAreaView()@property(nonatomic, strong) UIBezierPath *path1;@property(nonatomic, strong) UIBezierPath *path2;@property(nonatomic, strong) UIBezierPath *path3;@property(nonatomic, strong) UIBezierPath *path4;@end@implementation ScanAreaView- (void)drawRect:(CGRect)rect {    CGFloat lineWidth = 15.0;    CGFloat width = rect.size.width;    CGFloat height = rect.size.height;    //左上角    [self.path1 removeAllPoints];    [self.path1 moveToPoint:CGPointMake(0, lineWidth)];    [self.path1 addLineToPoint:CGPointMake(0, 0)];    [self.path1 addLineToPoint:CGPointMake(lineWidth, 0)];    self.path1.lineWidth = 5.0;    [[UIColor greenColor] set];    [self.path1 stroke];    //右上角    [self.path2 removeAllPoints];    [self.path2 moveToPoint:CGPointMake(width-lineWidth, 0)];    [self.path2 addLineToPoint:CGPointMake(width, 0)];    [self.path2 addLineToPoint:CGPointMake(width, lineWidth)];    self.path2.lineWidth = 5.0;    [[UIColor greenColor] set];    [self.path2 stroke];    //右下角    [self.path3 removeAllPoints];    [self.path3 moveToPoint:CGPointMake(width, height-lineWidth)];    [self.path3 addLineToPoint:CGPointMake(width, height)];    [self.path3 addLineToPoint:CGPointMake(width-lineWidth, height)];    self.path3.lineWidth = 5.0;    [[UIColor greenColor] set];    [self.path3 stroke];    //左下角    [self.path4 removeAllPoints];    [self.path4 moveToPoint:CGPointMake(0, height-lineWidth)];    [self.path4 addLineToPoint:CGPointMake(0, height)];    [self.path4 addLineToPoint:CGPointMake(lineWidth, height)];    self.path4.lineWidth = 5.0;    [[UIColor greenColor] set];    [self.path4 stroke];}-(UIBezierPath *)path1{    if (_path1==nil) {        _path1 = [UIBezierPath bezierPath];    }    return _path1;}-(UIBezierPath *)path2{    if (_path2==nil) {        _path2 = [UIBezierPath bezierPath];    }    return _path2;}-(UIBezierPath *)path3{    if (_path3==nil) {        _path3 = [UIBezierPath bezierPath];    }    return _path3;}-(UIBezierPath *)path4{    if (_path4==nil) {        _path4 = [UIBezierPath bezierPath];    }    return _path4;}@end

就这样了。挺简单的,这方面的资料网上一搜数不胜数。

没图没真相,好吧,我附上效果图。。。。

二维码效果图

条形码效果图

0 0