当前位置: 移动技术网 > IT编程>移动开发>IOS > 扫描二维码控件的封装iOS实现

扫描二维码控件的封装iOS实现

2019年07月24日  | 移动技术网IT编程  | 我要评论

酒曲,9c8832,文化街租房

扫描二维码效果

 

源码: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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网