美文网首页
二维码扫描加入手电筒的原生写法

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

作者: 高乔人 | 来源:发表于2018-06-27 17:11 被阅读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

    相关文章

      网友评论

          本文标题:二维码扫描加入手电筒的原生写法

          本文链接:https://www.haomeiwen.com/subject/ypvbyftx.html