废话不多说,直接上代码 创建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];
}