二维码扫描加入手电筒的原生写法

2018-06-27  本文已影响22人  高乔人

...

#import "WMQRCodeViewController.h"

#import "SVProgressHUD.h"

#define kDeviceVersion [[UIDevice currentDevice].systemVersion floatValue]

#define kScreenWidth  [UIScreen mainScreen].bounds.size.width

#define kScreenHeight [UIScreen mainScreen].bounds.size.height

#define kNavbarHeight ((kDeviceVersion>=7.0)?64:44)

#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)

#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)

#define kSCREEN_MAX_LENGTH (MAX(kScreenWidth, kScreenHeight))

#define kSCREEN_MIN_LENGTH (MIN(kScreenWidth, kScreenHeight))

#define IS_IPHONE4 (IS_IPHONE && kSCREEN_MAX_LENGTH <568.0)

#define IS_IPHONE5 (IS_IPHONE && kSCREEN_MAX_LENGTH ==568.0)

#define IS_IPHONE6 (IS_IPHONE && kSCREEN_MAX_LENGTH ==667.0)

#define IS_IPHONE6P (IS_IPHONE && kSCREEN_MAX_LENGTH ==736.0)

@importAVFoundation;

@interface WMQRCodeViewController (){

    UILabel* introLab;

    BOOLisLightOn;

    UIButton*mineQRCode;

    UIButton*theLightBtn;

    BOOLhasTheVC;

    BOOLisFirst;

    BOOLupOrdown;

    intnum;

    AVCaptureVideoPreviewLayer *preView;

    AVCaptureDevice*captureDevice;

    NSTimer* timer;

}

@property (nonatomic,strong) AVCaptureSession *session;

@property (nonatomic,weak) AVCaptureMetadataOutput *output;

@property (nonatomic,retain) UIImageView *lineIV;

/** 扫描支持的编码格式的数组 */

@property(nonatomic,strong)NSMutableArray* metadataObjectTypes;

@end

@implementationWMQRCodeViewController

- (NSMutableArray*)metadataObjectTypes{

    if (!_metadataObjectTypes) {

        _metadataObjectTypes = [NSMutableArray arrayWithObjects:AVMetadataObjectTypeAztecCode, AVMetadataObjectTypeCode128Code, AVMetadataObjectTypeCode39Code, AVMetadataObjectTypeCode39Mod43Code, AVMetadataObjectTypeCode93Code, AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypePDF417Code, AVMetadataObjectTypeQRCode, AVMetadataObjectTypeUPCECode, nil];

        // >= iOS 8

        if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_7_1) {

            [_metadataObjectTypes addObjectsFromArray:@[AVMetadataObjectTypeInterleaved2of5Code, AVMetadataObjectTypeITF14Code, AVMetadataObjectTypeDataMatrixCode]];

        }

    }

    return _metadataObjectTypes;

}

- (void)imagePickerControllerDidCancel:(UIImagePickerController*)picker{

    [self dismissViewControllerAnimated:YES completion:^{

        // [[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleDefault];

    }];

}

- (void)navigationController:(UINavigationController*)navigationController willShowViewController:(UIViewController*)viewController animated:(BOOL)animated{

    //[[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleDefault];

    viewController.navigationItem.leftBarButtonItem.tintColor = [UIColor whiteColor];

    viewController.navigationItem.rightBarButtonItem.tintColor = [UIColor whiteColor];

    NSDictionary *attributeDic = [NSDictionary dictionaryWithObjectsAndKeys:[UIColor whiteColor], NSForegroundColorAttributeName, [UIFont systemFontOfSize:17.0], NSFontAttributeName, nil];

    navigationController.navigationBar.titleTextAttributes= attributeDic;

}

- (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info {

    UIImage *image = [info objectForKey:UIImagePickerControllerEditedImage];

    if(!image) {

        image = [infoobjectForKey:UIImagePickerControllerOriginalImage];

    }

    ;

    [self dismissViewControllerAnimated:NO completion:^{

        //[[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleDefault];

    }];

    NSString*stringValue = [selfstringFromFileImage:image];

    [selfcheckQRcode:stringValue];

}

- (void)rightBarButtonItemPressed:(UIButton*)sender {

    // if (kDeviceVersion<=7.0) {

    // }

    // else {

    // self.detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{ CIDetectorAccuracy : CIDetectorAccuracyHigh }];

    // }

    UIImagePickerController *pickCtr = [[UIImagePickerController alloc] init];

    pickCtr.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;

    pickCtr.delegate=self;

    pickCtr.allowsEditing=NO;

    pickCtr.navigationBar.titleTextAttributes = [NSDictionary dictionaryWithObjectsAndKeys:[UIColor whiteColor], NSForegroundColorAttributeName, nil];

    [self presentViewController:pickCtr animated:YES completion:^{

    }];

    NSArray *vcs = self.navigationController.viewControllers;

    NSLog(@"vcs = %@",vcs);

}

-(void)initUI{

    isFirst=YES;

    upOrdown = NO;

    num=0;

    // 自定义导航右按钮

    NSString *name = [@"Resource.bundle" stringByAppendingPathComponent:@"fromPhoto"];

    UIImage*fromPhoto = [UIImageimageNamed:name];

    UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeCustom];

    rightButton.frame=CGRectMake(0,0, fromPhoto.size.width, fromPhoto.size.height);

    [rightButtonsetImage:fromPhoto forState:UIControlStateNormal];

    [rightButtonsetImage:fromPhoto forState:UIControlStateSelected];

    [rightButtonaddTarget:self action:@selector(rightBarButtonItemPressed:) forControlEvents:UIControlEventTouchUpInside];

    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithCustomView:rightButton];

}

- (void)startSessionRightNow:(NSNotification*)notification {

    //[timer resumeTimer];

    [self creatTimer];

    [_session startRunning];

}

- (void)viewDidAppear:(BOOL)animated {

    [superviewDidAppear:animated];

    if(isFirst)

    {

        [selfcreatTimer];

        [_session startRunning];

    }

    isFirst=NO;

}

- (void)viewWillDisappear:(BOOL)animated {

    [super viewWillDisappear:animated];

    [self deleteTimer];

    [[NSNotificationCenter defaultCenter]removeObserver:self name:@"startSession" object:nil];

}

- (void)viewDidDisappear:(BOOL)animated {

    [superviewDidDisappear:animated];

}

#pragma mark - 删除timer

- (void)deleteTimer

{

    if(timer) {

        [timerinvalidate];

        timer=nil;

    }

}

#pragma mark - 创建timer

- (void)creatTimer

{

    if(!timer) {

        timer=[NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:@selector(animation) userInfo:nil repeats:YES];

    }

}

- (void)viewWillAppear:(BOOL)animated {

    [superviewWillAppear:animated];

    [[NSNotificationCenter defaultCenter]  addObserver:self selector:@selector(startSessionRightNow:) name:@"startSession" object:nil];

    if(!isFirst) {

        [selfcreatTimer];

        [_session startRunning];

    }

}

- (void)viewDidLoad {

    self.navigationItem.title = @"扫一扫";

    self.view.backgroundColor = [UIColor colorWithWhite:0.2 alpha:1];

    [super viewDidLoad];

    [selfinitUI];

    [self setupDevice];

}

-(void)setupDevice{

    //1.初始化捕捉设备(AVCaptureDevice),类型为AVMediaTypeVideo

    captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

    NSError*error;

    //2.用captureDevice创建输入流input

    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];

    if(!input) {

        NSLog(@"%@", [error localizedDescription]);

        return;

    }

    //创建会话

    _session = [[AVCaptureSession alloc] init];

    [_session setSessionPreset:AVCaptureSessionPresetHigh];

    if([_sessioncanAddInput:input]) {

        [_sessionaddInput:input];

    }

    //预览视图

    preView = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_session];

    //设置预览图层填充方式

    [preView setVideoGravity:AVLayerVideoGravityResizeAspectFill];

    preView.frame = CGRectMake(kNavbarHeight / 2, kNavbarHeight + 30, self.view.frame.size.width - kNavbarHeight, self.view.frame.size.width - kNavbarHeight);

    [self.view.layer insertSublayer:preView atIndex:0];

    //输出

    AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];

    [outputsetMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];

    if([_sessioncanAddOutput:output]) {

        [_sessionaddOutput:output];

    }

    self.output= output;

    NSArray *arrTypes = output.availableMetadataObjectTypes;

    NSLog(@"%@",arrTypes);

    if ([_output.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeQRCode] || [_output.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeCode128Code]) {

        output.metadataObjectTypes=self.metadataObjectTypes;

        // [_session startRunning];

    }else{

        [_sessionstopRunning];

        //        rightButton.enabled = NO;

        UIAlertView*alert = [[UIAlertViewalloc]initWithTitle:@"抱歉!"message:@"相机权限被拒绝,请前往设置-隐私-相机启用此应用的相机权限。"delegate:selfcancelButtonTitle:nilotherButtonTitles:@"确定",nil];

        [alertshow];

        return;

    }

    UIImageView *codeFrame = [[UIImageView alloc] initWithFrame:preView.frame];

    codeFrame.contentMode = UIViewContentModeScaleAspectFit;

    NSString *name = [@"Resource.bundle" stringByAppendingPathComponent:@"codeframe"];

    [codeFramesetImage:[UIImageimageNamed:name]];

    [self.viewaddSubview:codeFrame];

    introLab = [[UILabel alloc] initWithFrame:CGRectMake(preView.frame.origin.x, preView.frame.origin.y + preView.frame.size.height, preView.frame.size.width, 40)];

    introLab.numberOfLines = 1;

    introLab.textAlignment = NSTextAlignmentCenter;

    introLab.textColor = [UIColor whiteColor];

    introLab.adjustsFontSizeToFitWidth = YES;

    introLab.text = @"将二维码/条码放入框内,即可自动扫描";

    [self.view addSubview:introLab];

    //我的二维码按钮

    mineQRCode = [UIButton buttonWithType:UIButtonTypeCustom];

    mineQRCode.frame = CGRectMake(self.view.frame.size.width / 2 - 100 / 2, introLab.frame.origin.y+introLab.frame.size.height - 5, 100, introLab.frame.size.height);

    [mineQRCode setTitle:@"我的二维码" forState:UIControlStateNormal];

    [mineQRCode setTitleColor:[UIColor redColor] forState:UIControlStateNormal];

    [mineQRCode addTarget:self action:@selector(showTheQRCodeOfMine:) forControlEvents:UIControlEventTouchUpInside];

    [self.view addSubview:mineQRCode];

    mineQRCode.hidden = YES;

    //theLightBtn

    theLightBtn = [UIButton buttonWithType:UIButtonTypeCustom];

    theLightBtn.frame = CGRectMake(self.view.frame.size.width / 2 - 100 / 2, mineQRCode.frame.origin.y + mineQRCode.frame.size.height + 20, 100, introLab.frame.size.height);

    NSString *lightName = [@"Resource.bundle" stringByAppendingPathComponent:@"light"];

    NSString *lightonName = [@"Resource.bundle" stringByAppendingPathComponent:@"lighton"];

    [theLightBtn setImage:[UIImage imageNamed:lightName] forState:UIControlStateNormal];

    [theLightBtn setImage:[UIImage imageNamed:lightonName] forState:UIControlStateSelected];

    [theLightBtn addTarget:self action:@selector(lightOnOrOff:) forControlEvents:UIControlEventTouchUpInside];

    [self.view addSubview:theLightBtn];

    if (![captureDevice isTorchAvailable]) {

        theLightBtn.hidden=YES;

    }

    // Start

    _lineIV = [[UIImageView alloc] initWithFrame:CGRectMake(preView.frame.origin.x, preView.frame.origin.y, preView.frame.size.width, 5)];

    NSString *lineName = [@"Resource.bundle" stringByAppendingPathComponent:@"line"];

    _lineIV.image= [UIImageimageNamed:lineName];

    [self.view addSubview:_lineIV];

    //开始扫描

    [_session startRunning];

}

//手电筒🔦的开和关

- (void)lightOnOrOff:(UIButton*)sender {

    sender.selected= !sender.selected;

    isLightOn = 1 - isLightOn;

    if (isLightOn) {

        [selfturnOnLed:YES];

    }

    else{

        [selfturnOffLed:YES];

    }

}

//打开手电筒

- (void) turnOnLed:(bool)update {

    [captureDevice lockForConfiguration:nil];

    [captureDevice setTorchMode:AVCaptureTorchModeOn];

    [captureDevice unlockForConfiguration];

}

//关闭手电筒

- (void) turnOffLed:(bool)update {

    [captureDevice lockForConfiguration:nil];

    [captureDevice setTorchMode: AVCaptureTorchModeOff];

    [captureDevice unlockForConfiguration];

}

- (void)showTheQRCodeOfMine:(UIButton*)sender {

    NSLog(@"showTheQRCodeOfMine");

}

- (void)animation {

    if(upOrdown==NO) {

        num++;

        _lineIV.frame = CGRectMake(preView.frame.origin.x, preView.frame.origin.y + 2 * num, preView.frame.size.width, 5);

        if (IS_IPHONE5||IS_IPHONE4) {

            if(2*num==preView.frame.size.height) {

                upOrdown=YES;

            }

        }

        else{

            if(2*num==preView.frame.size.height-3) {

                upOrdown=YES;

            }

        }

    }

    else{

        num--;

        _lineIV.frame = CGRectMake(preView.frame.origin.x, preView.frame.origin.y + 2 * num, preView.frame.size.width, 5);

        if(num==0) {

            upOrdown=NO;

        }

    }

}

#pragma mark - AVCaptureMetadataOutputObjectsDelegate

- (void)captureOutput:(AVCaptureOutput*)captureOutput didOutputMetadataObjects:(NSArray*)metadataObjects fromConnection:(AVCaptureConnection*)connection

{

    //判断是否有数据

    if(metadataObjects !=nil&& [metadataObjectscount] >0) {

        AVMetadataMachineReadableCodeObject*metadataObj = [metadataObjectsobjectAtIndex:0];

        //判断回传的数据类型

        if([[metadataObjtype]isEqualToString:AVMetadataObjectTypeQRCode]) {

            NSLog(@"stringValue = %@",metadataObj.stringValue);

            [selfcheckQRcode:metadataObj.stringValue];

        }else{

            NSLog(@"stringValue = %@",metadataObj.stringValue);

            [selfcheckQRcode:metadataObj.stringValue];

        }

    }

    [_session stopRunning];

    [self performSelector:@selector(startReading) withObject:nil afterDelay:0.5];

}

-(void)startReading{

    [_session startRunning];

}

-(void)stopReading{

    [_session stopRunning];

}

/**

 * 判断二维码

 */

- (void)checkQRcode:(NSString*)str{

    if(str.length==0) {

        UIAlertView*alert = [[UIAlertViewalloc]initWithTitle:@"找不到二维码"message:@"导入的图片里并没有找到二维码"delegate:selfcancelButtonTitle:@"确定"otherButtonTitles:nil];

        [alertshow];

        return;

    }

    if([strhasPrefix:@"http"]) {

        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:str]];

    }else{

        //弹出一个view显示二维码内容

        [SVProgressHUD showInfoWithStatus:str];

    }

    [SVProgressHUD dismissWithDelay:1.0];

}

/**

 * 将二维码图片转化为字符

 */

- (NSString*)stringFromFileImage:(UIImage*)img{

    intexifOrientation;

    switch (img.imageOrientation) {

        case UIImageOrientationUp:

            exifOrientation =1;

            break;

        case UIImageOrientationDown:

            exifOrientation =3;

            break;

        case UIImageOrientationLeft:

            exifOrientation =8;

            break;

        case UIImageOrientationRight:

            exifOrientation =6;

            break;

        case UIImageOrientationUpMirrored:

            exifOrientation =2;

            break;

        case UIImageOrientationDownMirrored:

            exifOrientation =4;

            break;

        case UIImageOrientationLeftMirrored:

            exifOrientation =5;

            break;

        case UIImageOrientationRightMirrored:

            exifOrientation =7;

            break;

        default:

            break;

    }

    NSDictionary *detectorOptions = @{ CIDetectorAccuracy : CIDetectorAccuracyHigh }; // TODO: read doc for more tuneups

    CIDetector*detector = [CIDetectordetectorOfType:CIDetectorTypeQRCodecontext:niloptions:detectorOptions];

    NSArray*features = [detectorfeaturesInImage:[CIImageimageWithCGImage:img.CGImage]];

    CIQRCodeFeature* qrStr  = (CIQRCodeFeature *)features.firstObject;

    //只返回第一个扫描到的二维码

    return qrStr.messageString;

}

-(void)dealloc{

    NSLog(@"%@ dealloc",NSStringFromClass(self.class));

}

- (void)didReceiveMemoryWarning {

    [super didReceiveMemoryWarning];

}

@end

...


demo点击 别忘了给个star

上一篇下一篇

猜你喜欢

热点阅读