iOS 扫一扫功能实现 —— HERO博客

来源:互联网 发布:做网络销售期货好做吗 编辑:程序博客网 时间:2024/06/08 04:17

调用系统原生接口实现扫一扫功能,可扫描识别二维码、条形码,识别相册图片。

首先看一下效果图:



下面贴上代码:

(如果测试机系统10.0及以上,在Info.plist文件添加如下语句:Privacy - Camera Usage Description、Privacy - Photo Library Usage Description
可参考我之前的一篇博客,iOS 10.0系统麦克风、相机等权限崩溃问题解决。)

AppDelegate.m:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];    self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[[ViewController alloc] init]];    self.window.backgroundColor = [UIColor whiteColor];    [self.window makeKeyAndVisible];        return YES;}

ViewController:

#import <UIKit/UIKit.h>@interface ViewController : UIViewController@end/*** ---------------分割线--------------- ***/#import "ViewController.h"#import "HWScanViewController.h"@implementation ViewController- (void)viewDidLoad {    [super viewDidLoad];    self.view.backgroundColor = [UIColor whiteColor];        //创建控件    [self creatControl];}- (void)creatControl{    //扫一扫按钮    UIButton *scanBtn = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, 100, 44)];    scanBtn.backgroundColor = [UIColor orangeColor];    [scanBtn setTitle:@"扫一扫" forState:UIControlStateNormal];    [scanBtn addTarget:self action:@selector(scanBtnOnClick) forControlEvents:UIControlEventTouchUpInside];    [self.view addSubview:scanBtn];}- (void)scanBtnOnClick{    HWScanViewController *vc = [[HWScanViewController alloc] init];    [self.navigationController pushViewController:vc animated:YES];}@end

HWScanViewController:

#import <UIKit/UIKit.h>@interface HWScanViewController : UIViewController@end/*** ---------------分割线--------------- ***/#import "HWScanViewController.h"#import <AVFoundation/AVFoundation.h>#define KMainW [UIScreen mainScreen].bounds.size.width#define KMainH [UIScreen mainScreen].bounds.size.height@interface HWScanViewController ()<AVCaptureMetadataOutputObjectsDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate>@property (nonatomic, strong) NSTimer *timer;@property (nonatomic, strong) AVCaptureDevice *device;@property (nonatomic, strong) AVCaptureSession *session;@property (nonatomic, strong) AVCaptureVideoPreviewLayer *preview;@property (nonatomic, weak) UIImageView *line;@property (nonatomic, assign) NSInteger distance;@end@implementation HWScanViewController- (void)viewDidLoad {    [super viewDidLoad];    //初始化信息    [self initInfo];        //创建控件    [self creatControl];        //设置参数    [self setupCamera];        //添加定时器    [self addTimer];}- (void)viewWillDisappear:(BOOL)animated{    [super viewWillDisappear:animated];        [self stopScanning];}- (void)initInfo{    //背景色    self.view.backgroundColor = [UIColor blackColor];        //导航标题    self.navigationItem.title = @"二维码/条形码";        //导航右侧相册按钮    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"相册" style:UIBarButtonItemStylePlain target:self action:@selector(photoBtnOnClick)];}- (void)creatControl{    CGFloat scanW = KMainW * 0.65;    CGFloat padding = 10.0f;    CGFloat labelH = 20.0f;    CGFloat tabBarH = 64.0f;    CGFloat cornerW = 26.0f;    CGFloat marginX = (KMainW - scanW) * 0.5;    CGFloat marginY = (KMainH - scanW - padding - labelH) * 0.5;        //遮盖视图    for (int i = 0; i < 4; i++) {        UIView *cover = [[UIView alloc] initWithFrame:CGRectMake(0, (marginY + scanW) * i, KMainW, marginY + (padding + labelH) * i)];        if (i == 2 || i == 3) {            cover.frame = CGRectMake((marginX + scanW) * (i - 2), marginY, marginX, scanW);        }        cover.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5f];        [self.view addSubview:cover];    }        //扫描视图    UIView *scanView = [[UIView alloc] initWithFrame:CGRectMake(marginX, marginY, scanW, scanW)];    [self.view addSubview:scanView];        //扫描线    UIImageView *line = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, scanW, 2)];    [self drawLineForImageView:line];    [scanView addSubview:line];    self.line = line;        //边框    UIView *borderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, scanW, scanW)];    borderView.layer.borderColor = [[UIColor whiteColor] CGColor];    borderView.layer.borderWidth = 1.0f;    [scanView addSubview:borderView];        //扫描视图四个角    for (int i = 0; i < 4; i++) {        CGFloat imgViewX = (scanW - cornerW) * (i % 2);        CGFloat imgViewY = (scanW - cornerW) * (i / 2);        UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(imgViewX, imgViewY, cornerW, cornerW)];        if (i == 0 || i == 1) {            imgView.transform = CGAffineTransformRotate(imgView.transform, M_PI_2 * i);        }else {            imgView.transform = CGAffineTransformRotate(imgView.transform, - M_PI_2 * (i - 1));        }        [self drawImageForImageView:imgView];        [scanView addSubview:imgView];    }        //提示标签    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(scanView.frame) + padding, KMainW, labelH)];    label.text = @"将二维码/条形码放入框内,即可自动扫描";    label.font = [UIFont systemFontOfSize:16.0f];    label.textAlignment = NSTextAlignmentCenter;    label.textColor = [UIColor whiteColor];    [self.view addSubview:label];        //选项栏    UIView *tabBarView = [[UIView alloc] initWithFrame:CGRectMake(0, KMainH - tabBarH, KMainW, tabBarH)];    tabBarView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.8f];    [self.view addSubview:tabBarView];        //开启照明按钮    UIButton *lightBtn = [[UIButton alloc] initWithFrame:CGRectMake(KMainW - 100, 0, 100, tabBarH)];    lightBtn.titleLabel.font = [UIFont systemFontOfSize:16.0f];    [lightBtn setTitle:@"开启照明" forState:UIControlStateNormal];    [lightBtn setTitle:@"关闭照明" forState:UIControlStateSelected];    [lightBtn addTarget:self action:@selector(lightBtnOnClick:) forControlEvents:UIControlEventTouchUpInside];    [tabBarView addSubview:lightBtn];}- (void)setupCamera{    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{        //初始化相机设备        _device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];         //初始化输入流        AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:_device error:nil];                //初始化输出流        AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];        //设置代理,主线程刷新        [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];                //初始化链接对象        _session = [[AVCaptureSession alloc] init];        //高质量采集率        [_session setSessionPreset:AVCaptureSessionPresetHigh];                if ([_session canAddInput:input]) [_session addInput:input];        if ([_session canAddOutput:output]) [_session addOutput:output];                //条码类型(二维码/条形码)        output.metadataObjectTypes = [NSArray arrayWithObjects:AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code, AVMetadataObjectTypeQRCode, nil];                //更新界面        dispatch_async(dispatch_get_main_queue(), ^{            _preview = [AVCaptureVideoPreviewLayer layerWithSession:_session];            _preview.videoGravity = AVLayerVideoGravityResizeAspectFill;            _preview.frame = CGRectMake(0, 0, KMainW, KMainH);            [self.view.layer insertSublayer:_preview atIndex:0];            [_session startRunning];        });    });}- (void)addTimer{    _distance = 0;    self.timer = [NSTimer scheduledTimerWithTimeInterval:0.01f target:self selector:@selector(timerAction) userInfo:nil repeats:YES];    [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];}- (void)timerAction{    if (_distance++ > KMainW * 0.65) _distance = 0;    _line.frame = CGRectMake(0, _distance, KMainW * 0.65, 2);}- (void)removeTimer{    [_timer invalidate];    _timer = nil;}//照明按钮点击事件- (void)lightBtnOnClick:(UIButton *)btn{    //判断是否有闪光灯    if (![_device hasTorch]) {        [self showAlertWithTitle:@"当前设备没有闪光灯,无法开启照明功能" message:nil sureHandler:nil cancelHandler:nil];        return;    }        btn.selected = !btn.selected;        [_device lockForConfiguration:nil];    if (btn.selected) {        [_device setTorchMode:AVCaptureTorchModeOn];    }else {        [_device setTorchMode:AVCaptureTorchModeOff];    }    [_device unlockForConfiguration];}//进入相册- (void)photoBtnOnClick{    if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {        UIImagePickerController *controller = [[UIImagePickerController alloc] init];        controller.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;        controller.delegate = self;                [self presentViewController:controller animated:YES completion:nil];    }else {        [self showAlertWithTitle:@"当前设备不支持访问相册" message:nil sureHandler:nil cancelHandler:nil];    }}#pragma mark - AVCaptureMetadataOutputObjectsDelegate- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{    //扫描完成    if ([metadataObjects count] > 0) {        //停止扫描        [self stopScanning];        //显示结果        [self showAlertWithTitle:@"扫描结果" message:[[metadataObjects firstObject] stringValue] sureHandler:nil cancelHandler:nil];    }}- (void)stopScanning{    [_session stopRunning];    _session = nil;    [_preview removeFromSuperlayer];    [self removeTimer];}#pragma mark - UIImagePickerControllrDelegate- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{    [picker dismissViewControllerAnimated:YES completion:^{        //获取相册图片        UIImage *image = info[UIImagePickerControllerOriginalImage];                //识别图片        CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{CIDetectorAccuracy:CIDetectorAccuracyHigh}];        NSArray *features = [detector featuresInImage:[CIImage imageWithCGImage:image.CGImage]];        //识别结果        if (features.count > 0) {            [self showAlertWithTitle:@"扫描结果" message:[[features firstObject] messageString] sureHandler:nil cancelHandler:nil];                    }else{            [self showAlertWithTitle:@"没有识别到二维码或条形码" message:nil sureHandler:nil cancelHandler:nil];        }    }];}//提示弹窗- (void)showAlertWithTitle:(NSString *)title message:(NSString *)message sureHandler:(void (^)())sureHandler cancelHandler:(void (^)())cancelHandler{    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];    UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDefault handler:sureHandler];    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:cancelHandler];    [alertController addAction:sureAction];    [alertController addAction:cancelAction];        [self presentViewController:alertController animated:YES completion:nil];}//绘制角图片- (void)drawImageForImageView:(UIImageView *)imageView{    UIGraphicsBeginImageContext(imageView.bounds.size);    //获取上下文    CGContextRef context = UIGraphicsGetCurrentContext();    //设置线条宽度    CGContextSetLineWidth(context, 6.0f);    //设置颜色    CGContextSetStrokeColorWithColor(context, [[UIColor greenColor] CGColor]);    //路径    CGContextBeginPath(context);    //设置起点坐标    CGContextMoveToPoint(context, 0, imageView.bounds.size.height);    //设置下一个点坐标    CGContextAddLineToPoint(context, 0, 0);    CGContextAddLineToPoint(context, imageView.bounds.size.width, 0);    //渲染,连接起点和下一个坐标点    CGContextStrokePath(context);        imageView.image = UIGraphicsGetImageFromCurrentImageContext();    UIGraphicsEndImageContext();}//绘制线图片- (void)drawLineForImageView:(UIImageView *)imageView{    CGSize size = imageView.bounds.size;    UIGraphicsBeginImageContext(size);    //获取上下文    CGContextRef context = UIGraphicsGetCurrentContext();    //创建一个颜色空间    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();    //设置开始颜色    const CGFloat *startColorComponents = CGColorGetComponents([[UIColor greenColor] CGColor]);    //设置结束颜色    const CGFloat *endColorComponents = CGColorGetComponents([[UIColor whiteColor] CGColor]);    //颜色分量的强度值数组    CGFloat components[8] = {startColorComponents[0], startColorComponents[1], startColorComponents[2], startColorComponents[3], endColorComponents[0], endColorComponents[1], endColorComponents[2], endColorComponents[3]    };    //渐变系数数组    CGFloat locations[] = {0.0, 1.0};    //创建渐变对象    CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, components, locations, 2);    //绘制渐变    CGContextDrawRadialGradient(context, gradient, CGPointMake(size.width * 0.5, size.height * 0.5), size.width * 0.25, CGPointMake(size.width * 0.5, size.height * 0.5), size.width * 0.5, kCGGradientDrawsBeforeStartLocation);    //释放    CGColorSpaceRelease(colorSpace);    CGGradientRelease(gradient);        imageView.image = UIGraphicsGetImageFromCurrentImageContext();    UIGraphicsEndImageContext();}@end

扫一扫Demo下载链接:http://code.cocoachina.com/view/134257
2 0