欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2023-12-16 19:11:10
扫描二维码效果   源码:https://github.com/youxianming/animations  // // qrco...

扫描二维码效果

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

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

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

上一篇:

下一篇: