二维码扫描

CIDetector 这个api是苹果在ios8之后提供的。所以用苹果自带的AVFundation扫描,如果从相册获取图片识别二维码,则需要8.0系统以上。

- (void)viewDidLoad {

[super viewDidLoad];

_captureSession = nil;

//初始化扫描界面

[self setScanView];

}

-(void)viewWillAppear:(BOOL)animated {

//10.开始扫描

[_captureSession startRunning];

[self createTimer];

}

-(void)viewWillDisappear:(BOOL)animated {

[self stopTimer];

[self stopReading];

}

//二维码的扫描区域

- (void)setScanView

{

self.view.backgroundColor = [UIColor clearColor];

UIView *scanView=[[UIView alloc] initWithFrame:CGRectMake(0,0, VIEW_WIDTH,VIEW_HEIGHT)];

[self.view addSubview:scanView];

_scanView = scanView;

_scanView.backgroundColor=[UIColor clearColor];

//最上部view

UIView* navView = [[UIView alloc] initWithFrame:CGRectMake(0,0, VIEW_WIDTH,SCANVIEW_EdgeTop - 40)];

navView.backgroundColor = kMainColorOfApp;

[_scanView addSubview:navView];

UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake((screenWith - 200)/2, 20, 200, 44)];

titleLabel.textColor = [UIColor whiteColor];

titleLabel.textAlignment = NSTextAlignmentCenter;

titleLabel.text = AppLocalizedString(@"Scan QR code");

[titleLabel setBackgroundColor:[UIColor clearColor]];

[navView addSubview:titleLabel];

//导航左边的按钮

UIButton *leftBarbtn = [[UIButton alloc] initWithFrame:CGRectMake(15, 30, 22, 22)];

[leftBarbtn setBackgroundImage:[UIImage imageNamed:@"back_normal_icon"] forState:UIControlStateNormal];

[leftBarbtn setBackgroundImage:[UIImage imageNamed:@"back_down_icon"] forState:UIControlStateHighlighted];

leftBarbtn.tag = kTagBtnLeft;

[leftBarbtn addTarget:self action:@selector(onBarbtnClick:) forControlEvents:UIControlEventTouchUpInside];

[navView addSubview:leftBarbtn];

//导航右边的按钮

UIButton *rightBarbtn = [[UIButton alloc] initWithFrame:CGRectMake(screenWith - 60 - 10, 20, 60, 44)];

[rightBarbtn setTitle:AppLocalizedString(@"Album") forState:UIControlStateNormal];

[rightBarbtn setTitle:AppLocalizedString(@"Album") forState:UIControlStateHighlighted];

rightBarbtn.tag = kTagBtnRight;

[rightBarbtn setTintColor:[UIColor blueColor]];

[rightBarbtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];

[rightBarbtn addTarget:self action:@selector(onBarbtnClick:) forControlEvents:UIControlEventTouchUpInside];

[navView addSubview:rightBarbtn];

[self setReadView];

//最上部view

UIView* upView = [[UIView alloc] initWithFrame:CGRectMake(0,SCANVIEW_EdgeTop - 40, VIEW_WIDTH,40)];

upView.alpha = TINTCOLOR_ALPHA;

upView.backgroundColor = [UIColor blackColor];

[_scanView addSubview:upView];

//左侧的view

UIView *leftView = [[UIView alloc] initWithFrame:CGRectMake(0,SCANVIEW_EdgeTop, SCANVIEW_EdgeLeft,VIEW_WIDTH-2*SCANVIEW_EdgeLeft)];

leftView.alpha =TINTCOLOR_ALPHA;

leftView.backgroundColor = [UIColor blackColor];

[_scanView addSubview:leftView];

//右侧的view

UIView *rightView = [[UIView alloc] initWithFrame:CGRectMake(VIEW_WIDTH-SCANVIEW_EdgeLeft,SCANVIEW_EdgeTop, SCANVIEW_EdgeLeft,VIEW_WIDTH-2*SCANVIEW_EdgeLeft)];

rightView.alpha =TINTCOLOR_ALPHA;

rightView.backgroundColor = [UIColor blackColor];

[_scanView addSubview:rightView];

//底部view

UIView *downView = [[UIView alloc] initWithFrame:CGRectMake(0,VIEW_WIDTH-2*SCANVIEW_EdgeLeft+SCANVIEW_EdgeTop,VIEW_WIDTH, VIEW_HEIGHT-(SCANVIEW_EdgeTop+VIEW_WIDTH-2*SCANVIEW_EdgeLeft))];

downView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:TINTCOLOR_ALPHA];

[_scanView addSubview:downView];

//用于说明的label

UILabel *labIntroudction= [[UILabel alloc] init];

labIntroudction.backgroundColor = [UIColor clearColor];

labIntroudction.frame=CGRectMake(0,5, VIEW_WIDTH,20);

labIntroudction.numberOfLines=1;

labIntroudction.font = [UIFont systemFontOfSize:15.0];

labIntroudction.textAlignment = NSTextAlignmentCenter;

labIntroudction.textColor = [UIColor whiteColor];

labIntroudction.text = AppLocalizedString(@"Align the QR Code within the frame to scan");

[downView addSubview:labIntroudction];

}

- (void)setReadView{

NSError *error;

//1.初始化捕捉设备(AVCaptureDevice),类型为AVMediaTypeVideo

AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

//2.用captureDevice创建输入流

AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];

if (!input) {

CCLog(@"扫描错误%@", [error localizedDescription]);

return ;

}

//3.创建媒体数据输出流

AVCaptureMetadataOutput *captureMetadataOutput = [[AVCaptureMetadataOutput alloc] init];

//4.实例化捕捉会话

_captureSession = [[AVCaptureSession alloc] init];

//高质量采集率

[_captureSession setSessionPreset:AVCaptureSessionPresetHigh];

//4.1.将输入流添加到会话

[_captureSession addInput:input];

//4.2.将媒体输出流添加到会话中

[_captureSession addOutput:captureMetadataOutput];

//5.1.设置代理

[captureMetadataOutput setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];

//5.2.设置输出媒体数据类型为QRCode

[captureMetadataOutput setMetadataObjectTypes:[NSArray arrayWithObject:AVMetadataObjectTypeQRCode]];

//6.实例化预览图层

AVCaptureVideoPreviewLayer *readerView = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_captureSession];

_readerView = readerView;

//7.设置预览图层填充方式

[readerView setVideoGravity:AVLayerVideoGravityResizeAspectFill];

//8.设置图层的frame

readerView.frame = CGRectMake(0,SCANVIEW_EdgeTop-40,screenWith,screenHeight-SCANVIEW_EdgeTop+40);

//9.将图层添加到预览view的图层上

[_scanView.layer insertSublayer:readerView atIndex:0];

//10.设置扫描范围

captureMetadataOutput.rectOfInterest = CGRectMake(0.2f, 0.2f, 0.8f, 0.8f);

//10.1.扫描框

UIImageView *boxView = [[UIImageView alloc] initWithFrame:CGRectMake(SCANVIEW_EdgeLeft,SCANVIEW_EdgeTop, VIEW_WIDTH-2*SCANVIEW_EdgeLeft,VIEW_WIDTH-2*SCANVIEW_EdgeLeft)];

_boxView = boxView;

boxView.image=[UIImage imageNamed:@"pick_bg.png"];

boxView.backgroundColor=[UIColor clearColor];

[_scanView addSubview:boxView];

//10.2.画中间的扫描线

//    _QrCodeline = [[UIImageView alloc] initWithFrame:CGRectMake(SCANVIEW_EdgeLeft,SCANVIEW_EdgeTop, VIEW_WIDTH-2*SCANVIEW_EdgeLeft,5)];

_QrCodeline = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,_boxView.frame.size.width,5)];

[_QrCodeline setImage:[UIImage imageNamed:@"line.png"]];

_QrCodeline.backgroundColor = [UIColor clearColor];

[_boxView addSubview:_QrCodeline];

}

//二维码的横线移动

- (void)moveScanLayer

{

CGRect frame = _QrCodeline.frame;

if (_boxView.frame.size.height-3 <= _QrCodeline.frame.origin.y) {

frame.origin.y = 0;

_QrCodeline.frame = frame;

frame.origin.y = _boxView.frame.size.height-2;

[UIView beginAnimations:nil context:nil];  //开始动画,第一个参数是该动画的名字

[UIView setAnimationDuration:1.6f];  //动画持续时间

_QrCodeline.frame = frame;

[UIView commitAnimations];  //结束动画

}else{

frame.origin.y = _boxView.frame.size.height-2;

[UIView beginAnimations:nil context:nil];  //开始动画,第一个参数是该动画的名字

[UIView setAnimationDuration:1.6f];  //动画持续时间

_QrCodeline.frame = frame;

[UIView commitAnimations];  //结束动画

}

}

- (void)createTimer

{

//创建一个时间计数

_timer=[NSTimer scheduledTimerWithTimeInterval:1.6f target:self selector:@selector(moveScanLayer) userInfo:nil repeats:YES];

[_timer fire];

}

- (void)stopTimer

{

if ([_timer isValid] == YES) {

[_timer invalidate];

_timer =nil;

}

}

#pragma mark - AVCaptureMetadataOutputObjectsDelegate

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection

{

[_captureSession stopRunning];

//判断是否有数据

if (metadataObjects != nil && [metadataObjects count] > 0) {

AVMetadataMachineReadableCodeObject *metadataObj = [metadataObjects objectAtIndex:0];

//判断回传的数据类型

if ([[metadataObj type] isEqualToString:AVMetadataObjectTypeQRCode]) {

[self readQRCodeActionWithCode:[metadataObj stringValue]];

}

}

}

-(void)stopReading{

[_captureSession stopRunning];

_captureSession = nil;

[_readerView removeFromSuperlayer];

[_QrCodeline removeFromSuperview];

}

/**

*  识别出来二维码之后的逻辑处理,以后有新的页面调用扫描时直接在这个方法里面增加逻辑就可以了

*

*  @param symbolStr

*/

- (void)readQRCodeActionWithCode:(NSString *)symbolStr

{

if([symbolStr hasPrefix:kQrcodeFriend]){

NSRange range = [symbolStr rangeOfString:kQrcodeFriend options:NSCaseInsensitiveSearch];

if (range.location != NSNotFound && range.location == 0) {

NSString *userId = [symbolStr stringByReplacingCharactersInRange:range withString:@""];

self.requestType = NearbyServiceType;

[[NearbyService sharedInstance] serchFriendbyUserIdOrNumber:userId andTarget:self andSuccessSelector:self.successSelector andFailureSelector:self.failureSelector];

} else {

//错误提示

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:AppLocalizedString(@"AppName") message:AppLocalizedString(@"QR code error") delegate:self cancelButtonTitle:AppLocalizedString(@"OK") otherButtonTitles:nil, nil];

alert.tag = kTagAlertDismiss;

[alert show];

}

}else if ([symbolStr hasPrefix:kQrcodeBalance]){

NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithDictionary:[[NSUserDefaults standardUserDefaults] objectForKey:GETWALLETINFO]];

NSMutableDictionary *dic1 = [dic objectForKey:[[CloudCall2AppDelegate sharedInstance] getUserID]];

NSNumber *isexist = [dic1 objectForKey:@"isexist"];

NSString *usertype = [dic1 objectForKey:@"usertype"];

NSRange range = [symbolStr rangeOfString:kQrcodeBalance options:NSCaseInsensitiveSearch];

if (range.location != NSNotFound && range.location == 0) {

if (!isexist.boolValue&&[usertype isEqualToString:@"V"]) {

[self showSetPayPasswordAlert];

}else if([usertype isEqualToString:@"M"]){

//错误提示

UIAlertView *alert = [[UIAlertView alloc]initWithTitle:nil message:AppLocalizedString(@"Pay function is forbid for Merchant account .") delegate:nil cancelButtonTitle:AppLocalizedString(@"OK") otherButtonTitles: nil];

alert.tag = kTagAlertDismiss;

[alert show];

}else{

NSString *gid = [symbolStr stringByReplacingCharactersInRange:range withString:@""];

self.requestType = BalanceServiceType;

[[BalanceService sharedInstance] initOrderWithGid:gid andTarget:self andSuccessSelector:self.successSelector andFailureSelector:self.failureSelector];

}

} else {

//错误提示

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:AppLocalizedString(@"AppName") message:AppLocalizedString(@"QR code error") delegate:self cancelButtonTitle:AppLocalizedString(@"OK") otherButtonTitles:nil, nil];

alert.tag = kTagAlertDismiss;

[alert show];

}

}else if ([symbolStr hasPrefix:kQrcodeAd]){

//给服务端发送一个请求

self.requestType = ADPlatformServiceType;

//截取二维码里面的广告id(依据后台服务端返回的协议)

NSArray *stringSeparateArr = [symbolStr componentsSeparatedByString:@"|"];

NSString *firstString = stringSeparateArr[0];

NSString *adIdString = [firstString substringFromIndex:4];//前面Adv# 这4个字符是固定的广告二维码标识,后面紧跟的是广告id

[[ADPlatformService sharedInstance] scanAdTwoDimensCodeWithADId:adIdString QrCode:symbolStr Target:self SuccessSelector:self.successSelector FailureSelector:self.failureSelector];

}else if ([symbolStr hasPrefix:kQrcodeWebLogin]){

//加密userid,格式化,再转json

NSString *userId = [[CloudCall2AppDelegate sharedInstance] getUserID];

NSData *useridData = [userId dataUsingEncoding:NSUTF8StringEncoding];

NSString *userIdBase64 = [useridData base64Encoding];

NSString *userIdFormat = [NSString stringWithFormat:@"\"userid\":\"%@\"",userIdBase64];

//        NSString *userIdJson = [userIdFormat JSONString];

//格式化uuid

NSString *uuid = [symbolStr substringFromIndex:6];

NSString *uuidJson = [NSString stringWithFormat:@"\"uuid\":\"%@\"",uuid];

//格式化sessionid 再加密

NSString *sessionId = [NSString stringWithFormat:@"{%@,%@}",userIdFormat,uuidJson];

NSData *sessionIdData = [sessionId dataUsingEncoding:NSUTF8StringEncoding];

NSString *sessionIdBase64 = [sessionIdData base64Encoding];

//作为参数上送

NSDictionary *sessidDicParam = @{@"sessionId":sessionIdBase64};

if (self.qrCodeWebLoginParamDic == nil) {

self.qrCodeWebLoginParamDic = sessidDicParam;

}

[[AFHttpRequest instance] ASyncPOSTHTTPS:kScanQRCodeLoginUrl  andParameters:[sessidDicParam mutableCopy] andUserInfo:[NSMutableDictionary dictionaryWithObjectsAndKeys:@"scanQRCodeLogin",@"reqtype",nil] andTarget:self andSuccessSelector:@selector(scanQRCodeRequestSuccess:andResponse:) andFailureSelector:@selector(scanQRCodeRequestFailed:andError:)];

}else{

[self dismissViewControllerAnimated:NO completion:^{

if ([symbolStr rangeOfString:@".aero"].length>0||[symbolStr rangeOfString:@".arpa"].length>0||[symbolStr rangeOfString:@".biz"].length>0||[symbolStr rangeOfString:@".com"].length>0||[symbolStr rangeOfString:@".coop"].length>0||[symbolStr rangeOfString:@".edu"].length>0||[symbolStr rangeOfString:@".gov"].length>0||[symbolStr rangeOfString:@".info"].length>0||[symbolStr rangeOfString:@".int"].length>0||[symbolStr rangeOfString:@".jobs"].length>0||[symbolStr rangeOfString:@".mil"].length>0||[symbolStr rangeOfString:@".name"].length>0||[symbolStr rangeOfString:@".museum"].length>0||[symbolStr rangeOfString:@".nato"].length>0||[symbolStr rangeOfString:@".net"].length>0||[symbolStr rangeOfString:@".org"].length>0||[symbolStr rangeOfString:@".pro"].length>0||[symbolStr rangeOfString:@".cn"].length>0||[symbolStr rangeOfString:@".co"].length>0) {

[self OpenWebBrowser:symbolStr];

}else if ([symbolStr hasPrefix:@"http:"] || [symbolStr hasPrefix:@"https:"] || [symbolStr hasPrefix:@"www."]){

[self OpenWebBrowser:symbolStr];

}else{

HUD = [[MBProgressHUD alloc] initWithView:self.view];

[self.nav.view addSubview:HUD];

HUD.mode = MBProgressHUDModeCustomView;

HUD.labelText = AppLocalizedString(@"QR code error");

[HUD show:YES];

[HUD hide:YES afterDelay:2];

}

}];

}

}

#pragma mark - Action- (void)onBarbtnClick:(id)sender {        UIButton *btn = (UIButton *)sender;        if (btn.tag == kTagBtnLeft) {                [self dismissViewControllerAnimated:YES completion:nil];            } else if(btn.tag == kTagBtnRight) {        UIImagePickerController *picker = [[UIImagePickerController alloc] init];        picker.allowsEditing = YES;        picker.delegate = self;        picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;        [self presentViewController:picker animated:YES completion:^{}];    }}#pragma mark - UIImagePickerControllerDelegate- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{    if (SystemVersion < 8.0) {                [self imagePickerControllerForiOS7:picker didFinishPickingMediaWithInfo:info];                return;        }else{                //获取用户设备型号        BOOL isIphone4and5 = NO;                //如果不是iphone5以上设备(于如果没有适配大屏,分辨率永远是568,这层拦截失效)        CGFloat height = [[UIScreen mainScreen] bounds].size.height;                if (height <= 568) {                        //获取用户设备具体型号            struct utsname systemInfo;                        uname(&systemInfo);                        NSString *deviceString            = [NSString stringWithCString:systemInfo.machine                                encoding:NSUTF8StringEncoding];                        //iphone5/iphone5c/iphone4s设备            if ([deviceString isEqualToString:@" iPhone5,3"]||[deviceString isEqualToString:@"iPhone5,4"]||[deviceString isEqualToString:@"iPhone5,1"]||[deviceString isEqualToString:@"iPhone5,2"]||[deviceString isEqualToString:@"iPhone4,1"]) {                                isIphone4and5 = YES;            }        }            if (isIphone4and5) {                        [self imagePickerControllerForiOS7:picker didFinishPickingMediaWithInfo:info];                        return;        }    }        //1.获取选择的图片    UIImage * image = [info objectForKey:UIImagePickerControllerOriginalImage];        //2.初始化一个监测器    CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{CIDetectorAccuracy:CIDetectorAccuracyHigh}];        [picker dismissViewControllerAnimated:YES completion:^{                //监测到的结果数组        NSArray *features = [detector featuresInImage:[CIImage imageWithCGImage:image.CGImage]];                if (features.count >=1) {                        /**结果对象 */            CIQRCodeFeature *feature = [features objectAtIndex:0];            NSString *scannedResult = feature.messageString;                        if (scannedResult.length) {                [self readQRCodeActionWithCode:scannedResult];                            } else {                                [[[UIAlertView alloc] initWithTitle:AppLocalizedString(@"AppName") message:AppLocalizedString(@"Decoding image file is not correct") delegate:nil cancelButtonTitle:AppLocalizedString(@"OK") otherButtonTitles:nil, nil]show];            }                    }else {                        [[[UIAlertView alloc] initWithTitle:AppLocalizedString(@"AppName") message:AppLocalizedString(@"Decoding image file is not correct") delegate:nil cancelButtonTitle:AppLocalizedString(@"OK") otherButtonTitles:nil, nil]show];        }    }];        [picker removeFromParentViewController];}- (void)imagePickerControllerForiOS7:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{    [picker dismissViewControllerAnimated:YES completion:^{                UIImage * image = [info objectForKey:UIImagePickerControllerOriginalImage];                //初始化        ZBarReaderController * read = [ZBarReaderController new];                //设置代理        read.readerDelegate = self;        CGImageRef cgImageRef = image.CGImage;        ZBarSymbol * symbol = nil;        idresults = [read scanImage:cgImageRef];

if ([info count]>2) {

int quality = 0;

for(ZBarSymbol *sym in results) {

int q = sym.quality;

if(quality < q) {

quality = q;

symbol = sym;

}

}

}else {

for(symbol in results)

break;

}

if (symbol != nil) {

NSString *symbolStr = [NSString stringWithCString:[symbol.data cStringUsingEncoding: NSShiftJISStringEncoding] encoding:NSUTF8StringEncoding];

[self readQRCodeActionWithCode:symbolStr];

//不用代理,统一在这里执行

//            if(_codeScanDelegate && [_codeScanDelegate respondsToSelector:@selector(CodeScanFinishWith:andResultCode:)]) {

//                [_codeScanDelegate CodeScanFinishWith:self andResultCode:symbolStr];

//            }

} else {

[[[UIAlertView alloc] initWithTitle:AppLocalizedString(@"AppName") message:AppLocalizedString(@"Decoding image file is not correct") delegate:nil cancelButtonTitle:AppLocalizedString(@"OK") otherButtonTitles:nil, nil]show];

}

}];

[picker removeFromParentViewController];

}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker

{

[self dismissViewControllerAnimated:YES completion:^{}];

}

你可能感兴趣的:(二维码扫描)