二维码iOS开发-知识合集iOS进阶指南

iOS原生二维码扫描仿微信扫码效果(fast effective

2016-09-03  本文已影响2109人  CharlesAir
always trust your self

MyZone


先看效果图

效果演示

录制gif好蛋疼,不是很流畅,扫描区域的动画效果(由小变大,类似微信效果)没有体现出来.有兴趣的可以研究下源码.😢😢😢😢


notice

注意关于生成二维码的,因为不是本篇文章的重点,所以不多提.项目中有一个生成二维码的UIImage+GenerateQRCode的分类,几乎涵盖了常见的二维码样式.直接拖过去用就可以了,提供如下方法

/**
 *  根据具体的内容生成二维码 //例如网址
 *
 *  @param contens 内容
 *
 *  @return 二维码图片
 */

+(nullable UIImage *)generateQRCodeViaContents:(nonnull NSString * )contens;

/**
 *  根据内容 和 尺寸生成相应的二维码
 *
 *  @param contens    内容
 *  @param QRCodeSize 正方形/只需要指定一个值即可
 *
 *  @return 二维码图片
 */

+(nullable UIImage *)generateQRCodeViaContents:(nonnull NSString *)contens withQRCodeSize:(CGFloat)QRCodeSize;

/**
 *  根据内容 尺寸 和 颜色生成二维码
 *
 *  @param contens    内容
 *  @param QRCodeSize 正方形/只需要指定一个值即可
 *  @param red
 *  @param green
 *  @param blue
 *  颜色不可以太接近白色
 *  @return   二维码图片
 */

+(nullable UIImage *)generateQRCodeViaContents:(nonnull NSString *)contens withQRCodeSize:(CGFloat)QRCodeSize forColorRed:(CGFloat)red colorGreen:(CGFloat)green colorBlue:(CGFloat)blue;

/**
 *  根据内容 尺寸 和 颜色 以及中心图片生成
 *  @param contens    内容
 *  @param QRCodeSize 正方形/只需要指定
 *  @param centerIMG  中心图片
 *  @return 二维码图片
 *  @param red        
 *  @param green      
 *  @param blue
 *
 *  @return 二维码图片
 */

+(nullable UIImage *)generateQRCodeViaContents:(nonnull NSString *)contens withQRCodeSize:(CGFloat)QRCodeSize withCenterImg:(nonnull UIImage *)centerIMG forColorRed:(CGFloat)red colorGreen:(CGFloat)green colorBlue:(CGFloat)blue;

项目目录结构

Screen Shot 2016-09-03 at 9.48.21 PM.png

因为是个小demo,所以就随便分了下文件夹,重点放在ScanVC就可以了.

/**
 *  扫描区域
 */
@property (nonatomic, strong) UIImageView * scView;

/**
 *  动画视图--扫描线
 */
@property (nonatomic, strong) UIImageView * animatorView;

/**
 *  创建设备会话对象
 */
@property (nonatomic, strong) AVCaptureSession * session;

/**
 *  预览视图
 */
@property (nonatomic, strong) AVCaptureVideoPreviewLayer * previewLayer;

/**
 *  获取摄像设备
 */
@property (nonatomic, strong) AVCaptureDevice * captureDevice;

/**
 *  输入流
 */
@property (nonatomic, strong) AVCaptureDeviceInput * captureInput;

/**
 *  输出流
 */
@property (nonatomic, strong) AVCaptureMetadataOutput * medataOutPut;

/**
 *  中间视图MaskView
 */
@property (nonatomic, strong) UIView * tempCenterMaskView;

/**
 *  对准二维码,进行扫码
 */
@property (nonatomic, strong) UILabel * indicatorLable;

/**
 *  菊花视图
 */
@property (nonatomic, strong) ScanLoadingView * loadingView;

上述视图大部分通过懒加载方式进行加载,但是注意AVCaptureSession属性如果通过懒加载的方式,结果就是二维码怎么也扫不出来,我至今也不明白为啥不行,有知道的朋友麻烦不吝赐教了😊😊. 因为比较简单,如果需要自定义样式的话,按图索骥自行替换就可.


ScanView的主要代码

#pragma mark - initialize

-(instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        
        
      //1.访问权限判断
        
        [self getPermissonToAccseeVidio];
        
    }
    
    return self;
}

首先当然是访问权限的判断了,用户同意授权以及不同意授权所对应的事件要清晰

/**
 *  访问权限判断
 */

-(void)getPermissonToAccseeVidio
{
    
    @weakify(self)
    
    //1.成功与否 都回到主线程更新ui操作
    
    [[PermissionManager manager] getCameraPermissonSuccessBlock:^{
        
        kDISPATCH_MAIN_THREAD(^{
           
            @strongify(self)
            
             [self successGetPermisson];
        });
        
    } failureBlock:^{
        
        kDISPATCH_MAIN_THREAD(^{
            
            @strongify(self)
            
            [self failureGetPermisson];
        });
        
    }];
    
}

通过单例的方式,管理整个项目的授权相关,并通过block回调的方式来做出对应的处理

/*
 *  成功获得访问权限
 */
-(void)successGetPermisson
{
    //1.添加扫描视图
    
    
    [self addScanView];
    
    
    //2.初始化session
    
    [self initSessionAbout];
    
    
    //3.添加遮罩效果
    
    [self addMaskView:self.scView];
    
    //4.添加扫描线
    
    [self addScanLine];
    
    //5.开始动画效果
    
    [self startScanAnimate];
}
/**
 *  未成功获得权限
 */
-(void)failureGetPermisson
{
    if ([self.delegate respondsToSelector:@selector(doNotGetPermissionToCamera)]) {
        
        [self.delegate doNotGetPermissionToCamera];
    }
}

此处通过代理回调给控制器,弹出时图,诱导用户给予权限

#pragma mark - AVCaptureMetadataOutputObjectsDelegate

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
    
    //1.播放系统提示音
    
    [SoundManager playSystemSound];
    
    if (metadataObjects.count>0) {
        
        AVMetadataMachineReadableCodeObject *metadataObject = [metadataObjects firstObject];
        
       @weakify(self)
        
        kDISPATCH_MAIN_THREAD(^{
           
            @strongify(self)
            
            //2.停止扫描
            [self stopScan];
    
            //3.显示菊花
            [self showLoadingView];
            
        });
    
#warning 一般在此处发送网络请求 此处做延时处理
        //3.发送网络请求
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            
            @strongify(self)
            //4.移除菊花
            
            [self dismissLoadingView];
            
            if ([self.delegate respondsToSelector:@selector(getScanResult:)]) {
                
                [self.delegate getScanResult:metadataObject.stringValue];
            }
            
        });
   
       
    }
}
+(void)playSystemSound
{

   // 1007 是短信提示音
    SystemSoundID soundID = 1007;
    
    AudioServicesPlaySystemSound(soundID);
}

很详细,此处就不再赘述了.详情见代码


demo地址


notice

1.以上代码仅供参考,如果有任何你觉得不对的地方,都可以联系我,我会第一时间回复,谢谢.
qq:391565521 email:zhuhaifei_ios@163.com

持续完善中,敬请期待.......

上一篇下一篇

猜你喜欢

热点阅读