美文网首页
iOS扫描功能

iOS扫描功能

作者: 始白 | 来源:发表于2019-03-28 17:05 被阅读0次

    扫描大概流程:

    1. 创建设备对象,输入输出对象(这个比较好理解,扫描毕竟需要手机设备,扫描肯定是有输入输出操作)
    2. 创建session来管理输入输出对象,设置扫描要支持的格式比如二维码条形码
    3. 设置扫描窗口,这个就是你要设置扫描作用域范围
    #import "ScanViewController.h"
    #import <AVFoundation/AVFoundation.h>
    #import <Photos/Photos.h>
    
    @interface ScanViewController ()<AVCaptureMetadataOutputObjectsDelegate,UIImagePickerControllerDelegate,UINavigationControllerDelegate>{
        AVCaptureSession *session;//输入输出的管理者
        AVCaptureDevice  *device;//获取摄像设备
        AVCaptureDeviceInput *input;//创建输入流
        AVCaptureMetadataOutput *output;//创建输出流
        AVCaptureVideoPreviewLayer *layer;//扫描窗口
        CGFloat imageX;
        CGFloat imageY;
    }
    @property (nonatomic, strong) UIImagePickerController *imagePickerVC;
    @property (nonatomic, strong) UIImageView *activeImage;
    @property (nonatomic, strong) UIButton  *torchButton;
    @end
    
    @implementation ScanViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        self.title = @"扫描";
        self.view.backgroundColor = [UIColor  whiteColor];
        
        self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:@"相册" style:UIBarButtonItemStylePlain target:self action:@selector(libraryPhoto)];
        imageX = DeviceSize.width*0.15;
        imageY = DeviceSize.width*0.15+64;
        // 判断相机权限
        [self checkCaptureStatus];
        [self initMaskView];
        [self initScan];
        
        [self performSelectorOnMainThread:@selector(timerFired) withObject:nil waitUntilDone:NO];
    }
    - (void)initMaskView{
        //扫描的框框
        UIImageView *scanImgView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"card_box2"]];
        scanImgView.frame = CGRectMake(imageX, imageY, DeviceSize.width*0.7, DeviceSize.width*0.7);
        [self.view addSubview:scanImgView];
        //扫描的线
        UIImageView *lineImgView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"card_thread"]];
        lineImgView.frame = CGRectMake(imageX, imageY, DeviceSize.width*0.7, 8);
        [self.view addSubview:lineImgView];
        self.activeImage = lineImgView;
        //扫描下面的提示按钮
        UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(scanImgView.frame), DeviceSize.width, 40)];
        label.text = @"将二维码放入框内即可自动扫描";
        label.textColor = [UIColor whiteColor];
        label.font = [UIFont systemFontOfSize:15];
        label.textAlignment = NSTextAlignmentCenter;
        [self.view addSubview:label];
        //添加全屏的黑色半透明蒙版
        UIView *maskView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, DeviceSize.width, DeviceSize.height+20)];
        maskView.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.5];
        [self.view addSubview:maskView];
        //从蒙版中扣出扫描框那一块,这块的大小尺寸将来也设成扫描输出的作用域大小
        UIBezierPath *maskPath = [UIBezierPath bezierPathWithRect:self.view.bounds];
        [maskPath appendPath:[[UIBezierPath bezierPathWithRect:CGRectMake(imageX, imageY, DeviceSize.width*0.7, DeviceSize.width*0.7)]bezierPathByReversingPath]];
        CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];
        maskLayer.path = maskPath.CGPath;
        maskView.layer.mask = maskLayer;
    }
    - (void)initScan{
        //获取摄像设备
        device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        //创建输入流
        input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
        //创建输出流
        output = [[AVCaptureMetadataOutput alloc]init];
        //设置代理  在主线程里刷新
        [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
        
        //初始化session
        session = [[AVCaptureSession alloc]init];
        //高质量采集率
        [session setSessionPreset:AVCaptureSessionPresetHigh];
        [session addInput:input];
        [session addOutput:output];
        //设置扫码支持的格式(二维码和条形码)
        output.metadataObjectTypes = @[AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN13Code,AVMetadataObjectTypeEAN8Code,AVMetadataObjectTypeCode128Code];
        layer = [AVCaptureVideoPreviewLayer layerWithSession:session];
        layer.videoGravity = AVLayerVideoGravityResizeAspectFill;
        //设置相机可是范围--全屏
        layer.frame = self.view.bounds;
        [self.view.layer insertSublayer:layer atIndex:0];
        //开始捕获
        [session startRunning];
     //设置扫描作用域范围(中间透明的扫描框)
        CGRect intertRect = [layer metadataOutputRectOfInterestForRect:CGRectMake(imageX, imageY, DeviceSize.width*0.7, DeviceSize.width*0.7)];
        
        output.rectOfInterest = intertRect;
    }
    //扫描线运动
    - (void)timerFired{
        [self.activeImage.layer addAnimation:[self time:2.5 Y:[NSNumber numberWithFloat:(DeviceSize.width*0.7-8)]] forKey:nil];
    }
    //动画 time单次滑动完成时间 y滑动距离
    - (CABasicAnimation *)time:(float)time Y:(NSNumber *)y{
        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.translation.y"];
        animation.toValue = y;
        animation.duration = time;
        animation.removedOnCompletion = YES;//yes返回原位置
        animation.repeatCount = MAXFLOAT;
        animation.fillMode = kCAFillModeForwards;
        return animation;
    }
    //代理方法扫描到的结果
    - (void)captureOutput:(AVCaptureOutput *)output didOutputMetadataObjects:(NSArray<__kindof AVMetadataObject *> *)metadataObjects fromConnection:(AVCaptureConnection *)connection{
        if (metadataObjects.count>0) {
            [session stopRunning];
            AVMetadataMachineReadableCodeObject *metadataObject = [metadataObjects objectAtIndex:0];
            NSLog(@"stringValue = %@",metadataObject.stringValue);
        }
    }
    - (void)checkCaptureStatus{
        // 判断是否支持相机
        AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
        if ((authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied)) {
            // 无权限
            UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"无法使用相机" message:@"请在iPhone的""设置-隐私-相机""中允许访问相机" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"设置", nil];
            [alert show];
        }
    }
    - (void)libraryPhoto{
        // 判断是否支持照片
        PHAuthorizationStatus authStatus = [PHPhotoLibrary authorizationStatus];
        if ((authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied)) {
            // 无权限
            UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"无法使用相册" message:@"请在iPhone的""设置""中允许访问照片" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"设置", nil];
            [alert show];
        } else {
            self.imagePickerVC = [[UIImagePickerController alloc]init];
            self.imagePickerVC.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
            self.imagePickerVC.mediaTypes = @[(NSString *)kUTTypeImage];
            self.imagePickerVC.delegate = self;
            self.imagePickerVC.allowsEditing = NO;
            self.imagePickerVC.navigationBar.barTintColor = [UIColor whiteColor];
            self.imagePickerVC.navigationBar.tintColor = kWord25Color;
            [self.imagePickerVC.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName : kWord25Color}];
            [self presentViewController:_imagePickerVC animated:YES completion:NULL];
        }
    }
    - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
        if (buttonIndex == 1) { // 去设置界面,开启相机访问权限
            if (ios8AndUper) {
                [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
            } else {
                
            }
        }
    }
    // 选择图片成功调用此方法
    - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info {
        UIImage *pickerImage = info[UIImagePickerControllerOriginalImage];
        CIImage *ciImage = [CIImage imageWithData:UIImagePNGRepresentation(pickerImage)];
        CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{CIDetectorAccuracy:CIDetectorAccuracyLow}];
        NSArray *features = [detector featuresInImage:ciImage];
        if (features.count >0) {
            CIQRCodeFeature *feature = features[0];
            NSLog(@"%@",feature.messageString);
        }
        [picker dismissViewControllerAnimated:NO completion:^{
        }];
    }
    // 取消图片选择调用此方法
    - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
        // dismiss UIImagePickerController
        [self dismissViewControllerAnimated:YES completion:nil];
    }
    //开灯按钮事件处理
    - (void)torchHandle{
        [self setTorch:![self torchIsOn]];
    }
    // 开关手电筒 status yes-开,no-关
    - (void)setTorch:(BOOL)status{
        if (TARGET_IPHONE_SIMULATOR){
            return;
        }
        Class captureDeviceClass = NSClassFromString(@"AVCaptureDevice");
        if (captureDeviceClass != nil) {
            AVCaptureDevice *device = [captureDeviceClass defaultDeviceWithMediaType:AVMediaTypeVideo];
            [device lockForConfiguration:nil];
            if ( [device hasTorch] ){
                if (status) {
                    [device setTorchMode:AVCaptureTorchModeOn];
                    [_torchButton setTitle:ZZYLocal(@"关灯") forState:UIControlStateNormal];
                }else{
                    [device setTorchMode:AVCaptureTorchModeOff];
                    [_torchButton setTitle:ZZYLocal(@"开灯") forState:UIControlStateNormal];
                }
            }
            [device unlockForConfiguration];
        }
    }
    //判断设备灯光开关
    - (BOOL)torchIsOn{
        if (TARGET_IPHONE_SIMULATOR) {
            return NO;
        }
        Class captureDeviceClass = NSClassFromString(@"AVCaptureDevice");
        if (captureDeviceClass != nil)
        {
            AVCaptureDevice *device = [captureDeviceClass defaultDeviceWithMediaType:AVMediaTypeVideo];
            if ( [device hasTorch] ){
                return [device torchMode] == AVCaptureTorchModeOn;
            }
            [device unlockForConfiguration];
        }
        return NO;
    }
    @end
    

    借鉴:https://www.jianshu.com/p/09742ec7ec78

    相关文章

      网友评论

          本文标题:iOS扫描功能

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