文档章节

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

hao1208hao
 hao1208hao
发布于 2016/07/28 12:31
字数 1298
阅读 17
收藏 0
点赞 0
评论 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
石家庄
程序员
常见的移动端H5页面开发遇到的坑和解决办法

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

webmirror ⋅ 05/02 ⋅ 0

基于 C# 开发的手机 APP 资产管理项目 - SmoSEC

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

smobiler ⋅ 06/06 ⋅ 0

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

支付宝也推出了“电子身份证”,但暂时只在杭州等 3 个城市可用

支付宝也推出了“电子身份证”,但暂时只在杭州等 3 个城市可用 2018-04-18 16:39编辑: suiling分类:业界动态来源:爱范儿 微信支付宝电子证件电子身份证 招聘信息: C++工程师 Cocos2d-x游...

suiling ⋅ 04/18 ⋅ 0

iOS宇宙大战游戏、调试工具、各种动画、AR相册、相机图片编辑等源码

iOS精选源码 日期时间选择器,swift(http://www.code4app.com/thread-30244-1-1.html) Space Battle 宇宙大战 SpriteKit游戏源码(http://www.code4app.com/thread-30246-1-1.html) LLDebugTo......

sunnyaigd ⋅ 06/19 ⋅ 0

姗姗来迟,微软推出智能手机视觉搜索功能

未来,也许手机摄像头而不是键盘才是鉴定猫猫狗狗、花花草草或消费者查找家具、服饰等商品信息的最快方式。今天,微软推出了Bing 移动版本的Visual Search视觉搜索工具,通过手机拍摄的照片提...

CashCat ⋅ 昨天 ⋅ 0

苹果与微信“短兵相接” “神仙打架”不能让用户买单

苹果与微信此次“短兵相接”,更多反映出两大巨头关于游戏规则的一场“暗战”。即便如此,也绝不能将绑架用户利益、通过随意更改产品功能,作为自己占领高地的“撒手锏”。无论苹果还是微信,...

六库科技 ⋅ 06/08 ⋅ 0

App打开微信小程序并传递参数

在App中打开小程序的功能发布有一段时间了,网上关于这个的新闻很多,但是技术资料并不多,我们有项目需要尝试这种方式,特意试了一下,发现还是有一些坑,分享给大家。 首先微信官方文档在微...

voxer ⋅ 06/12 ⋅ 0

嘿哥们,全国最大的“同性交友”APP了解一下?

嗯,是这样的,开源中国社区成立于2008年8月,旨在为中国的IT技术人员提供一个全面的、快捷更新的用来检索开源软件以及交流使用开源经验的平台。 当然,为了用户能够随时随地在社区中聊天、交...

oschina ⋅ 今天 ⋅ 0

5.7 类属性的set和get方法解析 [Swift原创教程]

原文:http://coolketang.com/staticCoding/5a9925ad9f5454507417fc90.html 1. get和set关键词被称为计算属性。它的目的是在取值和赋值时,执行里面的代码。本节课将为你讲解这两个关键词的使...

fzhlee ⋅ 05/06 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Sqoop

1.Sqoop: 《=》 SQL to Hadoop 背景 1)场景:数据在RDBMS中,我们如何使用Hive或者Hadoop来进行数据分析呢? 1) RDBMS ==> Hadoop(广义) 2) Hadoop ==> RDBMS 2)原来可以通过MapReduce I...

GordonNemo ⋅ 36分钟前 ⋅ 0

全量构建和增量构建的区别

1.全量构建每次更新时都需要更新整个数据集,增量构建只对需要更新的时间范围进行更新,所以计算量会较小。 2.全量构建查询时不需要合并不同Segment,增量构建查询时需要合并不同Segment的结...

无精疯 ⋅ 46分钟前 ⋅ 0

如何将S/4HANA系统存储的图片文件用Java程序保存到本地

我在S/4HANA的事务码MM02里为Material维护图片文件作为附件: 通过如下简单的ABAP代码即可将图片文件的二进制内容读取出来: REPORT zgos_api.DATA ls_appl_object TYPE gos_s_obj.DA...

JerryWang_SAP ⋅ 今天 ⋅ 0

云计算的选择悖论如何对待?

导读 人们都希望在工作和生活中有所选择。但心理学家的调查研究表明,在多种选项中进行选择并不一定会使人们更快乐,甚至不会产生更好的决策。心理学家Barry Schwartz称之为“选择悖论”。云...

问题终结者 ⋅ 今天 ⋅ 0

637. Average of Levels in Binary Tree - LeetCode

Question 637. Average of Levels in Binary Tree Solution 思路:定义一个map,层数作为key,value保存每层的元素个数和所有元素的和,遍历这个树,把map里面填值,遍历结束后,再遍历这个map,把每...

yysue ⋅ 今天 ⋅ 0

IDEA配置和使用

版本控制 svn IDEA版本控制工具不能使用 VCS-->Enable Version Control Integration File-->Settings-->Plugins 搜索Subversion,勾选SVN和Git插件 删除.idea文件夹重新生成项目 安装SVN客户......

bithup ⋅ 今天 ⋅ 0

PE格式第三讲扩展,VA,RVA,FA的概念

作者:IBinary 出处:http://www.cnblogs.com/iBinary/ 版权所有,欢迎保留原文链接进行转载:) 一丶VA概念 VA (virtual Address) 虚拟地址的意思 ,比如随便打开一个PE,找下它的虚拟地址 这边...

simpower ⋅ 今天 ⋅ 0

180623-SpringBoot之logback配置文件

SpringBoot配置logback 项目的日志配置属于比较常见的case了,之前接触和使用的都是Spring结合xml的方式,引入几个依赖,然后写个 logback.xml 配置文件即可,那么在SpringBoot中可以怎么做?...

小灰灰Blog ⋅ 今天 ⋅ 0

冒泡排序

原理:比较两个相邻的元素,将值大的元素交换至右端。 思路:依次比较相邻的两个数,将小数放在前面,大数放在后面。即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后。然后比较第...

人觉非常君 ⋅ 今天 ⋅ 0

Vagrant setup

安装软件 brew cask install virtualboxbrew cask install vagrant 创建project mkdir -p mst/vmcd mst/vmvagrant init hashicorp/precise64vagrant up hashicorp/precise64是一个box......

遥借东风 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部