文档章节

iOS扫描二维码和生成二维码

hao1208hao
 hao1208hao
发布于 2016/07/28 12:31
字数 1298
阅读 17
收藏 0

废话不多说,直接上代码 创建QRTool(生成二维码工具类)

#import <UIKit/UIKit.h>
@interface QRTool : NSObject
/**
 *  生成二维码
 *
 *  @param qrContent 二维码内容
 *  @param imgSize   二维码尺寸
 *
 *  @return 返回生成的二维码图片
 */
+(UIImage*)createQRImgWithContent:(NSString*)qrContent imgSize:(CGFloat)imgSize;
@end
#import "QRTool.h"
#import <CoreImage/CoreImage.h>

@implementation QRTool

+(UIImage *)createQRImgWithContent:(NSString *)qrContent imgSize :(CGFloat)imgSize{
    
    CIFilter* filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
    [filter setDefaults];
    
    NSData* data = [qrContent dataUsingEncoding:NSUTF8StringEncoding];
    [filter setValue:data forKeyPath:@"inputMessage"];
    CIImage* outImg = [filter outputImage];
    
    if (!imgSize) {
        imgSize = 200;
    }    
    return [self createNonInterpolatedUIImageFormCIImage:outImg withSize:imgSize];    
}

/**
 *  根据CIImage生成指定大小的UIImage
 *
 *  @param image CIImage
 *  @param size  图片宽度
 */
+ (UIImage *)createNonInterpolatedUIImageFormCIImage:(CIImage *)image withSize:(CGFloat) size
{
    CGRect extent = CGRectIntegral(image.extent);
    CGFloat scale = MIN(size/CGRectGetWidth(extent), size/CGRectGetHeight(extent));
    
    // 1.创建bitmap;
    size_t width = CGRectGetWidth(extent) * scale;
    size_t height = CGRectGetHeight(extent) * scale;
    CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray();
    CGContextRef bitmapRef = CGBitmapContextCreate(nil, width, height, 8, 0, cs, (CGBitmapInfo)kCGImageAlphaNone);
    CIContext *context = [CIContext contextWithOptions:nil];
    CGImageRef bitmapImage = [context createCGImage:image fromRect:extent];
    CGContextSetInterpolationQuality(bitmapRef, kCGInterpolationNone);
    CGContextScaleCTM(bitmapRef, scale, scale);
    CGContextDrawImage(bitmapRef, extent, bitmapImage);
    
    // 2.保存bitmap到图片
    CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);
    CGContextRelease(bitmapRef);
    CGImageRelease(bitmapImage);
    return [UIImage imageWithCGImage:scaledImage];
}

生成二维码调用: UIImage* img =[QRTool createQRImgWithContent:@"http://www.baidu.com" imgSize:200];

创建ScanQR(扫描二维码类)

#import <UIKit/UIKit.h>
@protocol scanResultDelegate <NSObject>
-(void)getScanResult:(NSString*)scanResult;
@end

@interface ScanQR : UIViewController
/** 扫描结果代理 */
@property(nonatomic,weak) id<scanResultDelegate> scanDelegate;
/**
 *  扫描二维码
 */
-(void)scanQR;
@end
#import "ScanQR.h"
#import "QRView.h"
#import <AVFoundation/AVFoundation.h>

@interface ScanQR ()<AVCaptureMetadataOutputObjectsDelegate>

@property (strong, nonatomic) AVCaptureSession *session;
@property (strong, nonatomic) AVCaptureDevice * device;
@property (strong, nonatomic) AVCaptureDeviceInput * input;
@property (strong, nonatomic) AVCaptureMetadataOutput * output;
/** 预览区 */
@property (strong, nonatomic) AVCaptureVideoPreviewLayer *preview;

@property (nonatomic,weak) QRView *qrView;
@end

@implementation ScanQR

- (void)viewDidLoad {
    [super viewDidLoad]; 
    [self scanQR];
}

-(void)scanQR{    
    AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
    if (status == AVAuthorizationStatusAuthorized) {
        //授权
        
    }else if(status == AVAuthorizationStatusNotDetermined){
        //未决定
    }else{
        //拒绝----弹窗提示跳转设置权限
        /*
        if ([[[UIDevice currentDevice]systemVersion]floatValue]>=8.0) {
           [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
         }else{
            NSURL*url=[NSURL URLWithString:@"prefs:root=Privacy"];
                [[UIApplication sharedApplication] openURL:url];
          }
        */
        return;
    }
    
    _device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    
    // Input
    _input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];
    
    // Output
    _output = [[AVCaptureMetadataOutput alloc]init];
    [_output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    
    // Session
    _session = [[AVCaptureSession alloc]init];
    [_session setSessionPreset:AVCaptureSessionPresetHigh];
    if ([_session canAddInput:self.input])
    {
        [_session addInput:self.input];
    }
    
    if ([_session canAddOutput:self.output])
    {
        [_session addOutput:self.output];
    }
    
    
    //增加条形码扫描
    // 条码类型 AVMetadataObjectTypeQRCode
    //_output.metadataObjectTypes =@[AVMetadataObjectTypeQRCode];
    _output.metadataObjectTypes = @[AVMetadataObjectTypeEAN13Code,
                                    AVMetadataObjectTypeEAN8Code,
                                    AVMetadataObjectTypeCode128Code,
                                    AVMetadataObjectTypeQRCode];
    
    // Preview
    _preview =[AVCaptureVideoPreviewLayer layerWithSession:_session];
    _preview.videoGravity =AVLayerVideoGravityResizeAspectFill;
    _preview.frame =self.view.layer.bounds;
    
    
    [self.view.layer insertSublayer:_preview atIndex:0];
    
    [_session startRunning];
   
    
    CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;
    CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
    
    CGRect screenRect = [UIScreen mainScreen].bounds;
    
    QRView *qrRectView = [[QRView alloc] initWithFrame:screenRect];
    
    CGFloat qrvX = 240;
    CGFloat qrvY = 240;
    
    qrRectView.transparentArea = CGSizeMake(qrvX, qrvY);
    qrRectView.backgroundColor = [UIColor clearColor];
    qrRectView.center = CGPointMake(screenWidth/ 2, screenHeight/ 2);
    [self.view addSubview:qrRectView];
    self.qrView = qrRectView;
    
    CGFloat cropY = (screenHeight - qrvY) / 2-120;
    if (screenHeight == 480) {
        cropY = (screenHeight - qrvY) / 2 - 60;
    }
    
    //修正扫描区域
    CGRect cropRect = CGRectMake((screenWidth - qrRectView.transparentArea.width) / 2,
                                 cropY,
                                 qrvX,
                                 qrvY);
    
    [_output setRectOfInterest:CGRectMake(cropRect.origin.y / screenHeight,
                                          cropRect.origin.x / screenWidth,
                                          cropRect.size.height / screenHeight,
                                          cropRect.size.width / screenWidth)];
    
}

#pragma mark - 实现output的回调方法
// 当扫描到数据时就会执行该方法
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
    if (metadataObjects.count > 0) {
        // 停止扫描
        [self.session stopRunning];
        [self.qrView stopAnimation];

        //震动提示
        AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
        
        AVMetadataMachineReadableCodeObject *object = [metadataObjects lastObject];
        
        [self getResult:object.stringValue];
        [self.navigationController popViewControllerAnimated:YES];
    } else {
        NSLog(@"没有扫描到数据");
    }
}

-(void)getResult:(NSString*)result{
    if ([self.scanDelegate respondsToSelector:@selector(getScanResult:)]) {
        [self.scanDelegate getScanResult:result];
    }
}

创建QRView 扫描区域

#import <UIKit/UIKit.h>
@interface QRView : UIView
/**
 *  透明的区域
 */
@property (nonatomic, assign) CGSize transparentArea;
//结束动画
-(void)stopAnimation;
@end
#import "QRView.h"
static NSTimeInterval kQrLineanimateDuration = 0.02;

@implementation QRView {
        UIImageView *qrLine;
        CGFloat qrLineY;
        UIButton *topBarView;
        NSTimer *timer;
}

- (void)layoutSubviews {    
    [super layoutSubviews];
    if (!qrLine) {
        [self initQRLine];
        timer = [NSTimer scheduledTimerWithTimeInterval:kQrLineanimateDuration target:self selector:@selector(show) userInfo:nil repeats:YES];
        [timer fire];
    }    
}

- (void)initQRLine {    
    
    CGFloat w = self.transparentArea.width;
    CGFloat h = self.transparentArea.height;
    
    qrLine  = [[UIImageView alloc] initWithFrame:CGRectMake((self.bounds.size.width - w) / 2, (self.bounds.size.height - h) / 2, w, 2)];
    //需要一张扫描线的图片,上下扫描
    qrLine.image = [UIImage imageNamed:@"qr_scan_line"];
    
    qrLine.contentMode = UIViewContentModeScaleAspectFill;
    [self addSubview:qrLine];
    //iPhone4 适配
    if ([UIScreen mainScreen].bounds.size.height == 480) {
        //iphone4s 
       qrLineY = qrLine.frame.origin.y+50;
    }else{
       qrLineY = qrLine.frame.origin.y;
    }    
}

- (void)show {   
    [UIView animateWithDuration:kQrLineanimateDuration animations:^{        
        CGRect rect = qrLine.frame;
        rect.origin.y = qrLineY;
        qrLine.frame = rect;
    } completion:^(BOOL finished) {
        CGFloat maxBorder = self.frame.size.height / 2 + self.transparentArea.height / 2 - 4-90;
       
        if ([UIScreen mainScreen].bounds.size.height == 480) {
            //iphone4s
            maxBorder = maxBorder +50;
        }

        if (qrLineY > maxBorder) {
            if ([UIScreen mainScreen].bounds.size.height == 480) {
                /** 扫描框起点 */
                qrLineY = self.frame.size.height / 2 - self.transparentArea.height /2-110+70;
            }else{
                qrLineY = self.frame.size.height / 2 - self.transparentArea.height /2-90;
            }            
        }
        qrLineY++;
    }];
}

- (void)drawRect:(CGRect)rect {
    
    //整个二维码扫描界面的颜色
    CGSize screenSize =[UIScreen mainScreen].bounds.size;
    CGRect screenDrawRect =CGRectMake(0, 0, screenSize.width,screenSize.height);
    
    //中间清空的矩形框
    CGRect clearDrawRect = CGRectMake(screenDrawRect.size.width / 2 - self.transparentArea.width / 2,
                                      screenDrawRect.size.height / 2 - self.transparentArea.height / 2-90,
                                      self.transparentArea.width,self.transparentArea.height);
    
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    [self addScreenFillRect:ctx rect:screenDrawRect];    
    [self addCenterClearRect:ctx rect:clearDrawRect];    
    [self addWhiteRect:ctx rect:clearDrawRect];    
    [self addCornerLineWithContext:ctx rect:clearDrawRect];    
}

- (void)addScreenFillRect:(CGContextRef)ctx rect:(CGRect)rect {
    
    CGContextSetRGBFillColor(ctx, 40 / 255.0,40 / 255.0,40 / 255.0,0.5);
    CGContextFillRect(ctx, rect);   //draw the transparent layer
}

- (void)addCenterClearRect :(CGContextRef)ctx rect:(CGRect)rect {
    //iPhone4 适配
    if ([UIScreen mainScreen].bounds.size.height == 480) {
        rect = CGRectMake(rect.origin.x, rect.origin.y +50, rect.size.width, rect.size.height);
    }
    CGContextClearRect(ctx, rect);  //clear the center rect  of the layer
}

- (void)addWhiteRect:(CGContextRef)ctx rect:(CGRect)rect {
    //iPhone4 适配
    if ([UIScreen mainScreen].bounds.size.height == 480) {
        rect = CGRectMake(rect.origin.x, rect.origin.y +50, rect.size.width, rect.size.height);
    }
    CGContextStrokeRect(ctx, rect);
    CGContextSetRGBStrokeColor(ctx, 1, 1, 1, 1);
    CGContextSetLineWidth(ctx, 0.8);
    CGContextAddRect(ctx, rect);
    CGContextStrokePath(ctx);
}

- (void)addCornerLineWithContext:(CGContextRef)ctx rect:(CGRect)rect{
    //iPhone4 适配
    if ([UIScreen mainScreen].bounds.size.height == 480) {
        rect = CGRectMake(rect.origin.x, rect.origin.y +50, rect.size.width, rect.size.height);
    }
    //画四个边角
    CGContextSetLineWidth(ctx, 2);
    CGContextSetRGBStrokeColor(ctx, 83 /255.0, 239/255.0, 111/255.0, 1);//绿色  
    
    //左上角
    CGPoint poinsTopLeftA[] = {
        CGPointMake(rect.origin.x+0.7, rect.origin.y),
        CGPointMake(rect.origin.x+0.7 , rect.origin.y + 15)
    };
    
    CGPoint poinsTopLeftB[] = {CGPointMake(rect.origin.x, rect.origin.y +0.7),CGPointMake(rect.origin.x + 15, rect.origin.y+0.7)};
    [self addLine:poinsTopLeftA pointB:poinsTopLeftB ctx:ctx];
    
    //左下角
    CGPoint poinsBottomLeftA[] = {CGPointMake(rect.origin.x+ 0.7, rect.origin.y + rect.size.height - 15),CGPointMake(rect.origin.x +0.7,rect.origin.y + rect.size.height)};
    CGPoint poinsBottomLeftB[] = {CGPointMake(rect.origin.x , rect.origin.y + rect.size.height - 0.7) ,CGPointMake(rect.origin.x+0.7 +15, rect.origin.y + rect.size.height - 0.7)};
    [self addLine:poinsBottomLeftA pointB:poinsBottomLeftB ctx:ctx];
    
    //右上角
    CGPoint poinsTopRightA[] = {CGPointMake(rect.origin.x+ rect.size.width - 15, rect.origin.y+0.7),CGPointMake(rect.origin.x + rect.size.width,rect.origin.y +0.7 )};
    CGPoint poinsTopRightB[] = {CGPointMake(rect.origin.x+ rect.size.width-0.7, rect.origin.y),CGPointMake(rect.origin.x + rect.size.width-0.7,rect.origin.y + 15 +0.7 )};
    [self addLine:poinsTopRightA pointB:poinsTopRightB ctx:ctx];
    
    CGPoint poinsBottomRightA[] = {CGPointMake(rect.origin.x+ rect.size.width -0.7 , rect.origin.y+rect.size.height+ -15),CGPointMake(rect.origin.x-0.7 + rect.size.width,rect.origin.y +rect.size.height )};
    CGPoint poinsBottomRightB[] = {CGPointMake(rect.origin.x+ rect.size.width - 15 , rect.origin.y + rect.size.height-0.7),CGPointMake(rect.origin.x + rect.size.width,rect.origin.y + rect.size.height - 0.7 )};
    [self addLine:poinsBottomRightA pointB:poinsBottomRightB ctx:ctx];
    CGContextStrokePath(ctx);
}

- (void)addLine:(CGPoint[])pointA pointB:(CGPoint[])pointB ctx:(CGContextRef)ctx {
    CGContextAddLines(ctx, pointA, 2);
    CGContextAddLines(ctx, pointB, 2);
}
-(void)stopAnimation
{
    [timer invalidate];
    timer = nil;
}

扫描调用示例

// 1.实现代理
-(void)scan{
    ScanQR *scan = [[ScanQR alloc]init];
    scan.scanDelegate = self;        
    [self.navigationController pushViewController:scan animated:YES];
}

// 扫描代理方法---获取扫描结果
-(void)getScanResult:(NSString *)scanResult{
    NSLog(@"扫描结果是:============%@",scanResult);    
    UIAlertView* alert = [[UIAlertView alloc]initWithTitle:@"扫描结果" message:scanResult delegate:nil cancelButtonTitle:nil otherButtonTitles:@"确定", nil];
    [alert show];    
}

© 著作权归作者所有

共有 人打赏支持
hao1208hao
粉丝 0
博文 3
码字总数 2237
作品 0
石家庄
程序员
越狱的 iPhone、iPad 通过网站实现一键安装 ipa 格式的 APP 应用

1、已经越狱的 iPhone、iPad 设备,当通过其自带的 safari 浏览器访问 ipa 应用下载网站时,利用 itms-services 协议,可以一键安装 ipa 文件的 iOS 应用,例如: <a href="itms-services:/...

问天123
2012/06/29
0
0
基于 C# 开发的手机 APP 资产管理项目 - SmoSEC

继SmoOne之后,又一款用C#开发的APP开源项目正式上线。 这款开源项目名为SmoSec,目前包含资产管理、耗材管理两大类。 并且,我们将会不断迭代,持续增加盘点、标签打印和仓库管理等功能。 ...

smobiler
06/06
0
0
常见的移动端H5页面开发遇到的坑和解决办法

手机共通问题 问题一:用同等比例的图片在PC机上很清楚,但是手机上很模糊,原因是什么呢? 经研究发现是devicePixelRatio作怪,因为手机分辨率太小,如果按照分辨率来显示网页字会非常小,所以苹果...

webmirror
05/02
0
0
【高德LBS开源组件大赛】iOS版地图选中Overlay功能组件

开源组件名称 iOS版地图选中Overlay功能组件 开源组件说明及使用场景 提供在iOS版地图中选中Overlay功能。使用场景很广泛,举个例子,搜索从A点到B点的公交路线时,地图上提供多条路线以供选...

cysgit
2014/07/23
0
2
iOS小白点效果、打地鼠游戏、轮播效果、画板、富文本编辑器等源码

iOS精选源码 美团外卖商家点菜页面(http://www.code4app.com/thread-29383-1-1.html) 板书录制演示程序(http://www.code4app.com/thread-29384-1-1.html) 分类轮播、直播间礼物列表轮播 -- O...

sunnyaigd
04/24
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Ubuntu18.04 显卡GF-940MX安装NVIDIA-390.77

解决办法: 下面就给大家一个正确的姿势在Ubuntu上安装Nvidia驱动: (a)首先去N卡官网下载自己显卡对应的驱动:www.geforce.cn/drivers (b)下载后好放在英文路径的目录下,怎么简单怎么来...

AI_SKI
今天
0
0
深夜胡思乱想

魔兽世界 最近魔兽世界出了新版本, 周末两天升到了满级,比之前的版本体验好很多,做任务不用抢怪了,不用组队打怪也是共享拾取的。技能简化了很多,哪个亮按哪个。 运维 服务器 产品 之间的...

Firxiao
今天
0
0
MySQL 8 在 Windows 下安装及使用

MySQL 8 带来了全新的体验,比如支持 NoSQL、JSON 等,拥有比 MySQL 5.7 两倍以上的性能提升。本文讲解如何在 Windows 下安装 MySQL 8,以及基本的 MySQL 用法。 下载 下载地址 https://dev....

waylau
今天
0
0
微信第三方平台 access_token is invalid or not latest

微信第三方开发平台code换session_key说的特别容易,但是我一使用就带来无穷无尽的烦恼,搞了一整天也无济于事. 现在记录一下解决问题的过程,方便后来人参考. 我遇到的这个问题搜索了整个网络也...

自由的开源
今天
2
0
openJDK之sun.misc.Unsafe类CAS底层实现

注:这篇文章参考了https://www.cnblogs.com/snowater/p/8303698.html 1.sun.misc.Unsafe中CAS方法 在sun.misc.Unsafe中CAS方法如下: compareAndSwapObject(java.lang.Object arg0, long a......

汉斯-冯-拉特
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部