二维码的生成和使用
###開篇 二維碼在軟件中的應用算是比較普遍的,常見的比如生成二維碼名片,掃碼支付,掃碼生成邀請碼等一系列操作。最近一直在完善掃碼部分的代碼和頁面邏輯,今天有空就一起整理一下整個流程相關的東西吧。 ####主要介紹內容
-
生成二維碼 商家端的生成二維碼供他人掃碼付款 生成自己的邀請二維碼供他人掃碼注冊 生成后的二維碼狀態刷新
-
二維碼掃描 掃碼頁面的布局,二維碼掃描框等所在頁面的處理 調用相機掃描二維碼 掃碼后的判斷來進行邏輯跳轉
-
長按識別相冊二維碼 相冊添加手勢長按識別二維碼
####生成二維碼 這里先放兩張被掃描的二維碼界面,分別是未被掃描和掃描中的頁面布局。
初始狀態 收款頁面的布局是確定的,包括付款成頭像,姓名,付款狀態等,會根據頁面所處的狀態進行顯示。 下圖顯示付款中的狀態
付款中 二維碼的生成代碼:
NSString *codeUrlString = [[[data objectForKey:@"data"] objectForKey:@"content"] objectForKey:@"url"];erweima_id =[[[data objectForKey:@"data"] objectForKey:@"content"] objectForKey:@"erweima_id"];ZXEncodeHints *hints = [ZXEncodeHints hints];hints.encoding = NSUTF8StringEncoding;// 設置編碼類型hints.errorCorrectionLevel = [ZXQRCodeErrorCorrectionLevel errorCorrectionLevelH]; // 設置糾正級別,越高識別越快ZXMultiFormatWriter *writer = [ZXMultiFormatWriter writer];ZXBitMatrix* result = [writer encode:codeUrlString format:kBarcodeFormatQRCode width:500 height:500 hints:hints error:&error];if (result) {CGImageRef image = [[ZXImage imageWithMatrix:result] cgimage];self.qrCodeImageView.image=[UIImage imageWithCGImage:image];} else {} 復制代碼這里使用的ZXingObJC庫生成的二維碼,生成之后創建定時器進行二維碼的刷新
[netRequestTimer invalidate];netRequestTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(ScanCodeStartNetworkRequest) userInfo:nil repeats:YES];[netRequestTimer fire]; 復制代碼在ScanCodeStartNetworkRequest中,進行網絡請求,根據后臺的返回的數據來進行二維碼狀態的判斷,看是處在未掃碼,付款中,還是付款成功等狀態,同時控制界面其他控件的顯示和隱藏。在付款成功后,根據后臺返回參數,展示自己提供的獎勵或其他界面。 注意:在頁面消失后要關閉定時器。 ####二維碼掃描 二維碼掃描頁面布局,確定他的界面顏色,亮色線條的上線滾動動畫,透明部分的范圍,邊界綠色框的繪制。當然也可以用第三方來設置這個界面上的view然后進行加載。
在二維碼界面中寫一個block來傳遞必要的參數,部分代碼如下 #import <UIKit/UIKit.h> typedef void(^QRUrlBlock)(NSString *url,NSString* invite_code,BOOL isResist); @interface QRViewController : UIViewController<UIAlertViewDelegate> @property (nonatomic, copy) QRUrlBlock qrUrlBlock; @end 復制代碼.m文件中調用相機,導入#import <AVFoundation/AVFoundation.h> 遵循AVCaptureMetadataOutputObjectsDelegate 部分代碼如下:
@interface QRViewController ()<AVCaptureMetadataOutputObjectsDelegate,QRViewDelegate>@property (strong, nonatomic) AVCaptureDevice * device; @property (strong, nonatomic) AVCaptureDeviceInput * input; @property (strong, nonatomic) AVCaptureMetadataOutput * output; @property (strong, nonatomic) AVCaptureSession * session; @property (strong, nonatomic) AVCaptureVideoPreviewLayer * preview;@end@implementation QRViewController- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.self.view.backgroundColor = [UIColor whiteColor];_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];}if([[[UIDevice currentDevice] systemVersion] floatValue]>= 7.0){//判斷相機是否能夠使用AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];if(status == AVAuthorizationStatusAuthorized) {// authorized_output.metadataObjectTypes =@[AVMetadataObjectTypeQRCode];_preview =[AVCaptureVideoPreviewLayer layerWithSession:_session];_preview.videoGravity =AVLayerVideoGravityResize;_preview.frame =self.view.layer.bounds;[self.view.layer insertSublayer:_preview atIndex:0];[_session startRunning];CGFloat displacementGap= 0.0;if (self.qr_type == QR_Type_AddFriend) {displacementGap = 60.0;}//此處創建之前 的設置掃面界面的View // CGRect screenRect = [UIScreen mainScreen].bounds;QRView *qrRectView = [[QRView alloc] initWithFrame:CGRectMake(0, -displacementGap, SCREEN_WIDTH, SCREEN_HEIGHT + displacementGap)];qrRectView.transparentArea = CGSizeMake(KQRWIDTH, KQRWIDTH);qrRectView.backgroundColor = [UIColor clearColor];// qrRectView.center = CGPointMake(self.view.frame.size.width / 2, self.view.frame.size.height / 2);qrRectView.delegate = self;self.view.backgroundColor = qrRectView.backgroundColor;[self.view addSubview:qrRectView];// UIButton *pop = [UIButton buttonWithType:UIButtonTypeCustom];// pop.frame = CGRectMake(20, 20, 50, 50);// [pop setTitle:@"返回" forState:UIControlStateNormal];// [pop addTarget:self action:@selector(pop:) forControlEvents:UIControlEventTouchUpInside];// [self.view addSubview:pop];//修正掃描區域CGFloat screenHeight = self.view.frame.size.height;CGFloat screenWidth = self.view.frame.size.width;CGRect cropRect = CGRectMake((screenWidth - qrRectView.transparentArea.width) / 2,(screenHeight - qrRectView.transparentArea.height) / 2,qrRectView.transparentArea.width,qrRectView.transparentArea.height);[_output setRectOfInterest:CGRectMake(cropRect.origin.y / screenHeight,cropRect.origin.x / screenWidth,cropRect.size.height / screenHeight,cropRect.size.width / screenWidth)];} else if(status == AVAuthorizationStatusDenied){// deniedUIAlertController * alertcontrol=[UIAlertController alertControllerWithTitle:@"未獲得授權使用攝像頭" message:@"請在ios“設置”-“隱私”-“相機”中打開!" preferredStyle:UIAlertControllerStyleAlert];UIAlertAction * action=[UIAlertAction actionWithTitle:@"知道了" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {[self.navigationController popViewControllerAnimated:YES];}];[alertcontrol addAction:action];[self presentViewController:alertcontrol animated:YES completion:nil];return ;} else if(status == AVAuthorizationStatusRestricted){// restrictedreturn;} else if(status == AVAuthorizationStatusNotDetermined){// not determined[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {if(granted){} else {return;}}];}}復制代碼在AVCaptureMetadataOutputObjectsDelegate協議方法中根據二維碼的信息來進行賦值和頁面跳轉,部分代碼如下:
#pragma mark AVCaptureMetadataOutputObjectsDelegate - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection {NSString *stringValue;if ([metadataObjects count] >0){//停止掃描[_session stopRunning];AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex:0];stringValue = metadataObject.stringValue;}//根據條件進行判斷 舉例如下 : if([stringValue rangeOfString:@"erweimahzb_id"].location != NSNotFound) {/*** 線下掃碼支付*/[self pop:nil];NSDictionary* dict=[self dictionaryFromQuery:[[stringValue componentsSeparatedByString:@"?"] objectAtIndex:1] usingEncoding:NSUTF8StringEncoding];if ([dict objectForKey:@"user_id"] && [dict objectForKey:@"erweimahzb_id"]) {if (self.qrUrlBlock) { //對block處理self.qrUrlBlock([dict objectForKey:@"user_id"],[dict objectForKey:@"erweimahzb_id"],0);}}else {[[[UIAlertView alloc] initWithTitle:@"溫馨提示" message:@"掃碼異常,請重新掃碼!" delegate:nil cancelButtonTitle:@"確定" otherButtonTitles:Nil, nil] show];}} 復制代碼通過以上思路我們設置完成二維碼掃描頁面后,在點擊對應按鈕彈出二維碼掃描的點擊事件里,完成block方法的實現 點擊事件在已經打開相機的前提下代碼處理如下:
//加載二維碼掃描的ControllerQRViewController *qrVC = [[QRViewController alloc] init];__block ProfileViewController *weakSelf = self;qrVC.qrUrlBlock=^(NSString* parent_id,NSString* invite_code,BOOL isResist){weakSelf.navigationController.navigationBar.hidden = YES;if (!isResist) { //如果不是掃描邀請注冊在這里處理數據,并實現跳轉邏輯}else{//如果是掃碼注冊界面在此處處理數據,并跳轉注冊界面} 復制代碼上述代碼只是做一個簡單的舉例,列出了實現思路,具體的邏輯根據自己項目的不同情況可做進一步的優化。 ####長按識別二維碼 給選擇的圖片添加長按手勢,在手勢的添加事件中進行判斷,代碼如下
if(gesture.state==UIGestureRecognizerStateBegan){UIImageView*tempImageView=(UIImageView*)gesture.view;if(tempImageView.image){CIDetector*detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{ CIDetectorAccuracy : CIDetectorAccuracyHigh }]; NSArray *features = [detector featuresInImage:[CIImage imageWithCGImage:tempImageView.image.CGImage]];//掃描結果CIQRCodeFeature *feature = [features objectAtIndex:0];NSLog(@"輸出掃描內容:%@",feature.messageString);}else if (gesture.state==UIGestureRecognizerStateEnded){}復制代碼###后記 二維碼比較常用到的一些功能做了一個簡單的介紹,可能有一些說的不是很恰當,希望發現的小伙伴積極指出。在接觸項目的同時也自己根據模塊歸納總結了一下,雖然沒有具體的代碼,但是主要的邏輯思路和主要部分的代碼已經有了,希望做個備忘,同時對大家有所幫助。(PS:簡書的雞湯文還是一如既往的多,各種xxx看我就夠了,我用XXX完成了XXX ,你XXX為什么XXX,真是夠夠的,希望自己能堅持下去,踏踏實實的寫點技術文章積累下自己吧!加油!)
總結
- 上一篇: SSL/TLS通信
- 下一篇: 使用nginx代理跨域,使用nginx代