iOS 二维码、条码扫描(带UI)

下面代码中待解决的问题:扫码过程中被打断(如按Home键),扫描动画会停止,需要做相应处理,在恢复前台时恢复动画。摄像头扫码使用iOS原生框架,从图片导入识别二维码使用ZXingObjC框架
//
//  BarCodeViewController.h
// 
//
//  Created by pilgrim on 16/5/11.
//  Copyright © 2016 pilgrim. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface BarCodeViewController : UIViewController

@end

//
//  BarCodeViewController.m
// 
//
//  Created by pilgrim on 16/5/11.
//  Copyright © 2016 pilgrim. All rights reserved.
//

#import "BarCodeViewController.h"
#import
<AVFoundation/AVFoundation.h>
#import
<ZXingObjC.h>
#import
"HomePageViewController.h"

@interface BarCodeViewController ()< AVCaptureMetadataOutputObjectsDelegate , UIImagePickerControllerDelegate , UINavigationControllerDelegate >


@property ( weak , nonatomic ) IBOutlet UIView *coverView;
// 从相册导入
@property ( weak , nonatomic ) IBOutlet UIButton *photoBtn;
// 灯光按钮
@property ( weak , nonatomic ) IBOutlet UIButton *lightBtn;

// 摄像头设备
@property ( strong , nonatomic ) AVCaptureDevice * device;
// 输入流
@property ( strong , nonatomic ) AVCaptureDeviceInput * input;
// 输出流
@property ( strong , nonatomic ) AVCaptureMetadataOutput * output;
//session
@property ( strong , nonatomic ) AVCaptureSession * session;
// 预览图层
@property ( strong , nonatomic ) AVCaptureVideoPreviewLayer * preview;

// 图片选择器
@property ( nonatomic , strong ) UIImagePickerController * imagePicker;
// 蒙版图层
@property ( nonatomic , strong ) CALayer * coverLayer;
// 刷新线
@property ( nonatomic , strong ) UIImageView * lineIV;

@end

@implementation BarCodeViewController

#pragma mark - 生命周期
- ( void )viewDidLoad {
    [
super viewDidLoad ];
   
   
// 设备
   
self . device = [ AVCaptureDevice defaultDeviceWithMediaType : AVMediaTypeVideo ];
   
   
// 输入流
   
NSError * error = nil ;
   
self . input = [ AVCaptureDeviceInput deviceInputWithDevice : self . device error :&error];
   
if (error) {
       
NSLog ( @" 输入流创建报错 " );
       
return ;
    }
   
   
// 输出流
   
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 ];
    }
   
   
self . output . metadataObjectTypes = [ NSArray arrayWithObjects : AVMetadataObjectTypeEAN13Code AVMetadataObjectTypeEAN8Code , AVMetadataObjectTypeCode128Code , AVMetadataObjectTypeQRCode , nil ];
   
// 扫描区域
   
self . output . rectOfInterest = CGRectMake (( float )(( YJScreenHeight - 64 ) / 2 - 120 ) / ( float )( YJScreenHeight - 64 ), ( float )( YJScreenWidth / 2 - 120 ) / ( float ) YJScreenWidth , 240.0 / ( float )( YJScreenHeight - 64 ), 240.0 / ( float ) YJScreenWidth );
   
   
//preview
   
self . preview = [ AVCaptureVideoPreviewLayer layerWithSession : self . session ];
   
self . preview . videoGravity = AVLayerVideoGravityResizeAspectFill ;
   
self . preview . backgroundColor = [[ UIColor blackColor ] colorWithAlphaComponent : 0.4 ]. CGColor ;
   
self . preview . frame = CGRectMake ( 0 , 0 , [ UIScreen mainScreen ]. bounds . size . width , [ UIScreen mainScreen ]. bounds . size . height - 64 );
    [
self . view . layer insertSublayer : self . preview atIndex : 0 ];
   
   
   
   
self . coverView . backgroundColor = [[ UIColor blackColor ] colorWithAlphaComponent : 0.5 ];
   
UIBezierPath *path = [ UIBezierPath bezierPathWithRect : CGRectMake ( 0 , 0 , YJScreenWidth , YJScreenHeight )];
    [path
appendPath :[[ UIBezierPath bezierPathWithRoundedRect : CGRectMake ( YJScreenWidth / 2 - 120 , ( YJScreenHeight - 64 ) / 2 - 120 , 240 , 240 ) cornerRadius : 0 ] bezierPathByReversingPath ]];
   
CAShapeLayer * maskLayer = [ CAShapeLayer layer ];
    maskLayer.
backgroundColor = [ UIColor whiteColor ]. CGColor ;
    maskLayer.
path = path. CGPath ;
   
self . coverView . layer . mask = maskLayer;
   
//    [self.view.layer insertSublayer:coverLayer atIndex:0];
}

- (
void )viewDidAppear:( BOOL )animated
{
#warning Need To Fix
    // 检测灯的状态,然后改按钮的状态
   
if ( self . session != nil ) {
       
if ( self . session . isRunning == NO ) {
            [
self . session startRunning ];
            [
self showAnimation ];
           
if ( self . coverLayer != nil ) {
                [
UIView animateWithDuration : 0.5 animations :^{
                   
self . coverLayer . backgroundColor = [[ UIColor blackColor ] colorWithAlphaComponent : 0 ]. CGColor ;
                }
completion :^( BOOL finished) {
                    [
self . coverLayer removeFromSuperlayer ];
                   
self . coverLayer = nil ;
                }];
            }
        }
    }
    [
super viewDidAppear :animated];
}

- (
void )viewDidDisappear:( BOOL )animated
{
    [
self . session stopRunning ];
    [
self stopAnimation ];
   
self . coverLayer = [ CALayer layer ];
   
self . coverLayer . frame = CGRectMake ( 0 , 0 , YJScreenWidth , YJScreenHeight );
   
self . coverLayer . backgroundColor = [[ UIColor blackColor ] colorWithAlphaComponent : 0.8 ]. CGColor ;
    [
self . view . layer addSublayer : self . coverLayer ];
    [
super viewDidDisappear :animated];
}

#pragma mark - 按钮点击事件
/**
 * 
从相册导入按钮点击事件
 *
 *  @param sender
按钮
 */

- (
IBAction )photoBtnDidClick:( UIButton *)sender {
   
self . imagePicker = [[ UIImagePickerController alloc ] init ];
   
self . imagePicker . delegate = self ;
   
self . imagePicker . allowsEditing = YES ;
   
self . imagePicker . sourceType = UIImagePickerControllerSourceTypePhotoLibrary ;
    [
self . navigationController presentViewController : self . imagePicker animated : YES completion :^{
    }];
}

/**
 * 
闪光灯按钮点击事件
 *
 *  @param sender
按钮
 */

- (
IBAction )lightBtnDidClick:( UIButton *)sender {
   
BOOL isLightOpened = [ self isLightOpened ];
   
   
if (isLightOpened) {
        [sender
setTitle : @" 开灯 " forState : UIControlStateNormal ];
    }
   
else
    {
        [sender
setTitle : @" 关灯 " forState : UIControlStateNormal ];
    }
   
    [
self openLight :!isLightOpened];
}

// 闪光灯
- (
BOOL )isLightOpened
{
   
if (![ self . device hasTorch ]) {
       
return NO ;
    }
else {
       
if ([ self . device torchMode ] == AVCaptureTorchModeOn ) {
           
return YES ;
        }
else {
           
return NO ;
        }
    }
}

- (
void )openLight:( BOOL )open
{
   
if (![ self . device hasTorch ]) {
    }
else {
       
if (open) {
           
// 开启闪光灯
           
if ( self . device . torchMode != AVCaptureTorchModeOn ||
              
self . device . flashMode != AVCaptureFlashModeOn ){
                [
self . device lockForConfiguration : nil ];
                [
self . device setTorchMode : AVCaptureTorchModeOn ];
                [
self . device setFlashMode : AVCaptureFlashModeOn ];
                [
self . device unlockForConfiguration ];
            }
        }
else {
           
// 关闭闪光灯
           
if ( self . device . torchMode != AVCaptureTorchModeOff ||
              
self . device . flashMode != AVCaptureFlashModeOff ){
                [
self . device lockForConfiguration : nil ];
                [
self . device setTorchMode : AVCaptureTorchModeOff ];
                [
self . device setFlashMode : AVCaptureFlashModeOff ];
                [
self . device unlockForConfiguration ];
            }
        }
    }
}

// 扫描动画
- (
void )showAnimation
{
   
if ( self . lineIV == nil ) {
       
self . lineIV = [[ UIImageView alloc ] initWithFrame : CGRectMake ( YJScreenWidth / 2 - 120 , ( YJScreenHeight - 64 ) / 2 - 120 , 240 , 2 )];
       
self . lineIV . backgroundColor = [ UIColor greenColor ];
        [
self . view addSubview : self . lineIV ];
       
       
CABasicAnimation * animate = [ CABasicAnimation animationWithKeyPath : @"position" ];
        animate.
fromValue = [ NSValue valueWithCGPoint : CGPointMake ( YJScreenWidth / 2 , ( YJScreenHeight - 64 ) / 2 - 120 )];
        animate.
toValue = [ NSValue valueWithCGPoint : CGPointMake ( YJScreenWidth / 2 , ( YJScreenHeight - 64 ) / 2 + 120 )];
        animate.
duration = 3.0 ;
        animate.
repeatCount = INT_MAX ;
        [
self . lineIV . layer addAnimation :animate forKey : nil ];
    }
}

- (
void )stopAnimation
{
   
if ( self . lineIV ) {
        [
self . lineIV . layer removeAllAnimations ];
        [
self . lineIV removeFromSuperview ];
       
self . lineIV = nil ;
    }
}

#pragma mark AVCaptureMetadataOutputObjectsDelegate
- ( void )captureOutput:( AVCaptureOutput *)captureOutput didOutputMetadataObjects:( NSArray *)metadataObjects fromConnection:( AVCaptureConnection *)connection
{
   
NSString *stringValue;
   
if ([metadataObjects count ] > 0 )
    {
       
AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex : 0 ];
        stringValue = metadataObject.
stringValue ;
       
NSLog ( @"stringValue:%@" , stringValue);
        [
self . session stopRunning ];
        [
self stopAnimation ];
       
HomePageViewController * nextVC = [[ HomePageViewController alloc ] initWithNibName : @"HomePageViewController" bundle : nil ];
        [
self . navigationController pushViewController :nextVC animated : YES ];
       
//        DetailViewController * detailVC = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil];
//        detailVC.detailURLStr = stringValue;
//        [self.navigationController pushViewController:detailVC animated:YES];
    }
}

#pragma mark - UIImagePickerViewControllerDelegate
- ( void )imagePickerController:( UIImagePickerController *)picker didFinishPickingMediaWithInfo:( NSDictionary < NSString *, id > *)info
{
   
UIImage * image = info[ UIImagePickerControllerEditedImage ];
   
NSLog ( @"image:%@" , image);
   
    [
self . navigationController dismissViewControllerAnimated : YES completion :^{
       
       
self . imagePicker = nil ;
       
       
CGImageRef imageToDecode = image. CGImage // Given a CGImage in which we are looking for barcodes
       
       
ZXLuminanceSource *source = [[ ZXCGImageLuminanceSource alloc ] initWithCGImage :imageToDecode];
       
ZXBinaryBitmap *bitmap = [ ZXBinaryBitmap binaryBitmapWithBinarizer :[ ZXHybridBinarizer binarizerWithSource :source]];
       
       
NSError *error = nil ;
       
       
// There are a number of hints we can give to the reader, including
       
// possible formats, allowed lengths, and the string encoding.
       
ZXDecodeHints *hints = [ ZXDecodeHints hints ];
       
       
ZXMultiFormatReader *reader = [ ZXMultiFormatReader reader ];
       
ZXResult *result = [reader decode :bitmap
                                   
hints :hints
                                   
error :&error];
       
if (result) {
           
// The coded result as a string. The raw data can be accessed with
           
// result.rawBytes and result.length.
           
NSString *contents = result. text ;
           
NSLog ( @"result:%@" , contents);
           
HomePageViewController * nextVC = [[ HomePageViewController alloc ] initWithNibName : @"HomePageViewController" bundle : nil ];
            [
self . navigationController pushViewController :nextVC animated : YES ];
           
           
// The barcode format, such as a QR code or UPC-A
           
//        ZXBarcodeFormat format = result.barcodeFormat;
        }
else {
            [
self showHUDInWindowJustWithText : @" 未发现条码 " disMissAfterDelay : 1.0 ];
           
// Use error to determine why we didn't get a result, such as a barcode
           
// not being found, an invalid checksum, or a format inconsistency.
        }
    }];
   
   
}

- (
void )didReceiveMemoryWarning {
    [
super didReceiveMemoryWarning ];
   
// Dispose of any resources that can be recreated.
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/


@end
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值