• 扫描二维码控件的封装


    扫描二维码控件的封装

    效果

    源码

    https://github.com/YouXianMing/Animations

    //
    //  QRCodeView.h
    //  QRCode
    //
    //  Created by YouXianMing on 16/7/7.
    //  Copyright © 2016年 XianMing You. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    #import <AVFoundation/AVFoundation.h>
    @class QRCodeView;
    
    @protocol QRCodeViewDelegate <NSObject>
    
    @optional
    
    /**
     *  获取QR的扫描结果
     *
     *  @param codeView   QRCodeView实体对象
     *  @param codeString 扫描字符串
     */
    - (void)QRCodeView:(QRCodeView *)codeView codeString:(NSString *)codeString;
    
    @end
    
    @interface QRCodeView : UIView
    
    /**
     *  代理
     */
    @property (nonatomic, weak) id <QRCodeViewDelegate> delegate;
    
    /**
     *  灯的状态,默认为关闭
     */
    @property (nonatomic) AVCaptureTorchMode torchMode;
    
    /**
     *  敏感区域,如果不设置,则为全部扫描区域
     */
    @property (nonatomic) CGRect interestArea;
    
    /**
     *  你用来添加自定义控件的view,尺寸与当前初始化的view一致
     */
    @property (nonatomic, strong) UIView *contentView;
    
    /**
     *  正在运行当中
     */
    @property (nonatomic, readonly) BOOL  isRunning;
    
    /**
     *  开始扫描
     *
     *  @return 如果成功,则返回YES,否则返回NO
     */
    - (BOOL)start;
    
    /**
     *  结束扫描
     */
    - (void)stop;
    
    @end
    //
    //  QRCodeView.m
    //  QRCode
    //
    //  Created by YouXianMing on 16/7/7.
    //  Copyright © 2016年 XianMing You. All rights reserved.
    //
    
    #import "QRCodeView.h"
    
    @interface QRCodeView () <AVCaptureMetadataOutputObjectsDelegate>
    
    @property (nonatomic) BOOL                                 isRunning;
    @property (nonatomic, strong) UIView                      *videoView;
    
    @property (nonatomic, strong) AVCaptureDeviceInput        *deviceInput;
    @property (nonatomic, strong) AVCaptureDevice             *captureDevice;
    @property (nonatomic, strong) AVCaptureSession            *captureSession;
    @property (nonatomic, strong) AVCaptureVideoPreviewLayer  *videoPreviewLayer;
    @property (nonatomic, strong) AVCaptureMetadataOutput     *captureMetadataOutput;
    
    @end
    
    @implementation QRCodeView
    
    - (instancetype)initWithFrame:(CGRect)frame {
        
        if (self = [super initWithFrame:frame]) {
            
            self.videoView = [[UIView alloc] initWithFrame:self.bounds];
            [self addSubview:self.videoView];
            
            self.contentView = [[UIView alloc] initWithFrame:self.bounds];
            [self addSubview:self.contentView];
            
            self.captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
            
            _torchMode = AVCaptureTorchModeOff;
            
            [self addNotificationCenter];
        }
        
        return self;
    }
    
    #pragma mark - NSNotificationCenter related.
    
    - (void)addNotificationCenter {
        
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(notificationCenterEvent:)
                                                     name:AVCaptureInputPortFormatDescriptionDidChangeNotification
                                                   object:nil];
    }
    
    - (void)removeNotificationCenter {
        
        [[NSNotificationCenter defaultCenter] removeObserver:self
                                                        name:AVCaptureInputPortFormatDescriptionDidChangeNotification
                                                      object:nil];
    }
    
    - (void)notificationCenterEvent:(NSNotification *)sender {
        
        if (self.interestArea.size.width && self.interestArea.size.height) {
            
            self.captureMetadataOutput.rectOfInterest = [self.videoPreviewLayer metadataOutputRectOfInterestForRect:self.interestArea];
            
        } else {
            
            self.captureMetadataOutput.rectOfInterest = CGRectMake(0, 0, 1, 1);
        }
    }
    
    #pragma mark - Start & Stop.
    
    - (BOOL)start {
        
        // 初始化输入流
        BOOL     result  = NO;
        NSError *error   = nil;
        self.deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:self.captureDevice error:&error];
        if (self.deviceInput == nil) {
            
            NSLog(@"%@", error);
            return result;
        }
        
        // 创建会话
        self.captureSession = [[AVCaptureSession alloc] init];
        
        // 添加输入流
        [self.captureSession addInput:self.deviceInput];
        
        // 初始化输出流
        self.captureMetadataOutput = [[AVCaptureMetadataOutput alloc] init];
        
        // 添加输出流
        [self.captureSession addOutput:self.captureMetadataOutput];
        
        // 创建queue.
        [self.captureMetadataOutput setMetadataObjectsDelegate:self queue:dispatch_queue_create(nil, nil)];
        self.captureMetadataOutput.metadataObjectTypes = @[AVMetadataObjectTypeQRCode];
        
        // 创建输出对象
        self.videoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.captureSession];
        self.videoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
        self.videoPreviewLayer.frame = self.contentView.bounds;
        [self.videoView.layer addSublayer:self.videoPreviewLayer];
        
        // 开始
        [self.captureSession startRunning];
        self.isRunning = YES;
        result         = YES;
        
        return result;
    }
    
    - (void)stop {
        
        [self.captureSession stopRunning];
        self.isRunning      = NO;
        self.captureSession = nil;
    }
    
    #pragma mark - AVCaptureMetadataOutputObjectsDelegate
    
    - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects
           fromConnection:(AVCaptureConnection *)connection {
        
        if (metadataObjects.count > 0) {
            
            AVMetadataMachineReadableCodeObject *metadata = metadataObjects.firstObject;
            NSString                            *result   = nil;
            
            if ([metadata.type isEqualToString:AVMetadataObjectTypeQRCode]) {
                
                result = metadata.stringValue;
                
                if (_delegate && [_delegate respondsToSelector:@selector(QRCodeView:codeString:)]) {
                    
                    [_delegate QRCodeView:self codeString:result];
                }
            }
        }
    }
    
    #pragma mark - Setter & Getter.
    
    - (void)setTorchMode:(AVCaptureTorchMode)torchMode {
    
        _torchMode = torchMode;
        
        if (_deviceInput && [self.captureDevice hasTorch]) {
            
            [self.captureDevice lockForConfiguration:nil];
            [self.captureDevice setTorchMode:torchMode];
            [self.captureDevice unlockForConfiguration];
        }
    }
    
    #pragma mark - System method.
    
    - (void)dealloc {
        
        [self stop];
        [self removeNotificationCenter];
    }
    
    @end
  • 相关阅读:
    开挂的列表与矜持的元组
    烦人的字符串
    好用的for循环与range
    浅谈编码
    流程控制与循环
    基础运算符
    python初识
    python的小介绍
    来自极客标签10款最新设计素材-系列九
    chmod----改变一个或多个文件的存取模式(mode)
  • 原文地址:https://www.cnblogs.com/YouXianMing/p/5653311.html
Copyright © 2020-2023  润新知