ios7 蘋果原生二維碼掃描(和微信類似)

在ios7蘋果推出了二維碼掃描,以前想要做二維碼掃描,只能通過第三方ZBar與ZXing。

ZBar在掃描的靈敏度上,和內存的使用上相對于ZXing上都是較優的,但是對于 “圓角二維碼” 的掃描確很困難。

ZXing 是 Google Code上的一個開源的條形碼掃描庫,是用java設計的,連Google Glass 都在使用的。但有人為了追求更高效率以及可移植性,出現了c++ port. Github上的Objectivc-C port,其實就是用OC代碼封裝了一下而已,而且已經停止維護。這樣效率非常低,在instrument下面可以看到CPU和內存瘋漲,在內存小的機器上很容易崩潰。

AVFoundation無論在掃描靈敏度和性能上來說都是最優的。

首先要導入#import <AVFoundation/AVFoundation.h>框架

?

?其次還需要授權應用可以訪問相機

    // 判斷相機是否授權使用相機AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];if(status == AVAuthorizationStatusAuthorized) {} else if(status == AVAuthorizationStatusDenied){// NSLog(@"denied不允許");return ;} else if(status == AVAuthorizationStatusNotDetermined){[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {if(granted){
//                NSLog(@"允許");} else {
//                NSLog(@"不允許");return;}}];}//    typedef enum
//        AVAuthorizationStatusNotDetermined = 0, // 用戶尚未做出選擇這個應用程序的問候
//        AVAuthorizationStatusRestricted,        // 此應用程序沒有被授權訪問的照片數據。可能是家長控制權限
//        AVAuthorizationStatusDenied,            // 用戶已經明確否認了這一照片數據的應用程序訪問
//        AVAuthorizationStatusAuthorized         // 用戶已經授權應用訪問照片數據} CLAuthorizationStatus;

?

?

完成二維碼掃描大致有十個步驟:

    // 1.獲取輸入設備AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];// 2.創建輸入對象NSError *error;AVCaptureDeviceInput *inPut = [[AVCaptureDeviceInput alloc] initWithDevice:device error:&error];if (inPut == nil) {UIAlertView *aler = [[UIAlertView alloc] initWithTitle:@"提示" message:@"設備不可用" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"確定", nil];[self.view addSubview:aler];[aler show];return;}// 3.創建輸出對象AVCaptureMetadataOutput *outPut = [[AVCaptureMetadataOutput alloc] init];// 4.設置代理監聽輸出對象的輸出流  (說明:使用主線程隊列,相應比較同步,使用其他隊列,相應不同步,容易讓用戶產生不好的體驗)
    [outPut setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];// 5.創建會話AVCaptureSession *session = [[AVCaptureSession alloc] init];self.session = session;// 6.將輸入和輸出對象添加到會話if ([session canAddInput:inPut]) {[session addInput:inPut];}if ([session canAddOutput:outPut]) {[session addOutput:outPut];}// 7.告訴輸出對象, 需要輸出什么樣的數據  // 提示:一定要先設置會話的輸出為output之后,再指定輸出的元數據類型!
    [outPut setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]];// 8.創建預覽圖層AVCaptureVideoPreviewLayer *preViewLayer = [AVCaptureVideoPreviewLayer layerWithSession:session];preViewLayer.frame = self.view.bounds;[self.view.layer insertSublayer:preViewLayer atIndex:0];// 9.設置掃面范圍outPut.rectOfInterest = CGRectMake(0.2, 0.18, 0.6, 0.5);// 10.設置掃描框UIView *boxView = [[UIView alloc] initWithFrame:CGRectMake(0.2 * SrceenW, 0.18 * SrceenH, 0.6 * SrceenW, 0.5 * SrceenH)];self.boxView = boxView;boxView.layer.borderColor = [UIColor yellowColor].CGColor;boxView.layer.borderWidth = 3;[self.view addSubview:boxView];// 設置掃描線CALayer *scanLayer = [[CALayer alloc] init];self.scanLayer = scanLayer;scanLayer.frame = CGRectMake(0, 0, boxView.bounds.size.width, 2);scanLayer.backgroundColor = [UIColor redColor].CGColor;[boxView.layer addSublayer:scanLayer];// 開始掃描[session startRunning];

其中第9個步驟是可以優化內存的

@property(nonatomic)?CGRect?rectOfInterest;

這個屬性大致意思就是告訴系統它需要注意的區域,大部分APP的掃碼UI中都會有一個框,提醒你將條形碼放入那個區域,這個屬性的作用就在這里,它可以設置一個范圍,只處理在這個范圍內捕獲到的圖像的信息。如此一來,我們代碼的效率又會得到很大的提高,在使用這個屬性的時候。需要幾點注意:

1、這個CGRect參數和普通的Rect范圍不太一樣,它的四個值的范圍都是0-1,表示比例。

2、經過測試發現,這個參數里面的x對應的恰恰是距離左上角的垂直距離,y對應的是距離左上角的水平距離。

3、寬度和高度設置的情況也是類似。

?

/// 經過測試 ?使用rectOfInterest 更改掃描范圍 并沒有很好的可控制范圍,如果想達到想微信那樣,只有在固定的掃描框中才可以掃描成功

? ? 可以使用以下設置,在

-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection; 方法中,判斷二維碼的三個坐標點是否在掃描框中。

?

for (id objects in metadataObjects) {// 判斷檢測到的對象類型if (![objects isKindOfClass:[AVMetadataMachineReadableCodeObject class]]) {return;}// 轉換對象坐標
AVMetadataMachineReadableCodeObject *obj = (AVMetadataMachineReadableCodeObject *)[preViewLayer transformedMetadataObjectForMetadataObject:objects];// 判斷掃描范圍if (!CGRectContainsRect(self.boxView.frame, obj.bounds)) {continue;}}

?

?

?

?

-----------------------------以下是源碼:

#import "ScanQrcodeVController.h"

@protocol ScanQrcodeVControllerDelegate <NSObject>
// 二維碼返回結果
-(void)scanQrcodeWithNString:(NSString *) ruselt;
@end
@interface ScanQrcodeVController : UIViewController
@property (nonatomic, weak) id<ScanQrcodeVControllerDelegate>delegate;
@end

#import "ScanQrcodeVController.m"

@interface ScanQrcodeVController ()<AVCaptureMetadataOutputObjectsDelegate>
// 會話
@property (nonatomic, strong) AVCaptureSession *session;
// 定時器
@property (nonatomic, strong) CADisplayLink *link;
// 掃描線
@property (nonatomic, strong) CALayer *scanLayer;
// 掃描框
@property (nonatomic, weak) UIView *boxView;
/// 保存二維碼結果
@property (nonatomic, copy) NSString *string;
@end@implementation ScanQrcodeVController
- (void)viewDidLoad {[super viewDidLoad];self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"NavBack"] style:UIBarButtonItemStylePlain target:self action:@selector(goBack)];self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"確定" style:UIBarButtonItemStylePlain target:self action:@selector(doneClick)];[self scanCode];  
}-(void)scanCode {CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(updataFrame)];self.link = link;link.frameInterval = 3;[link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];

  

? ??// 判斷相機是否授權使用相機

 

? ? AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];

 

? ? if(status == AVAuthorizationStatusAuthorized) {

 

? ? } else if(status == AVAuthorizationStatusDenied){

 

?? ? ? // NSLog(@"denied不允許");

 

? ? ? ? return ;

 

? ? } else if(status == AVAuthorizationStatusNotDetermined){

 

? ? ? ? [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {

 

? ? ? ? ? ? if(granted){

 

//? ? ? ? ? ? ? ? NSLog(@"允許");

 

? ? ? ? ? ? } else {

 

//? ? ? ? ? ? ? ? NSLog(@"不允許");

 

? ? ? ? ? ? ? ? return;

 

? ? ? ? ? ? }

 

? ? ? ? }];

 

? ? // 1.獲取輸入設備

    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];// 2.創建輸入對象NSError *error;AVCaptureDeviceInput *inPut = [[AVCaptureDeviceInput alloc] initWithDevice:device error:&error];if (inPut == nil) {UIAlertView *aler = [[UIAlertView alloc] initWithTitle:@"提示" message:@"設備不可用" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"確定", nil];[self.view addSubview:aler];[aler show];return;}// 3.創建輸出對象AVCaptureMetadataOutput *outPut = [[AVCaptureMetadataOutput alloc] init];// 4.設置代理監聽輸出對象的輸出流  說明:使用主線程隊列,相應比較同步,使用其他隊列,相應不同步,容易讓用戶產生不好的體驗
    [outPut setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];// 5.創建會話AVCaptureSession *session = [[AVCaptureSession alloc] init];self.session = session;// 6.將輸入和輸出對象添加到會話if ([session canAddInput:inPut]) {[session addInput:inPut];}if ([session canAddOutput:outPut]) {[session addOutput:outPut];}// 7.告訴輸出對象, 需要輸出什么樣的數據  // 提示:一定要先設置會話的輸出為output之后,再指定輸出的元數據類型!
    [outPut setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]];// 8.創建預覽圖層AVCaptureVideoPreviewLayer *preViewLayer = [AVCaptureVideoPreviewLayer layerWithSession:session];preViewLayer.frame = self.view.bounds;[self.view.layer insertSublayer:preViewLayer atIndex:0];// 9.設置掃面范圍outPut.rectOfInterest = CGRectMake(0.2, 0.18, 0.6, 0.5);// 10.設置掃描框UIView *boxView = [[UIView alloc] initWithFrame:CGRectMake(0.2 * SrceenW, 0.18 * SrceenH, 0.6 * SrceenW, 0.5 * SrceenH)];self.boxView = boxView;boxView.layer.borderColor = [UIColor yellowColor].CGColor;boxView.layer.borderWidth = 3;[self.view addSubview:boxView];// 設置掃描線CALayer *scanLayer = [[CALayer alloc] init];self.scanLayer = scanLayer;scanLayer.frame = CGRectMake(0, 0, boxView.bounds.size.width, 2);scanLayer.backgroundColor = [UIColor redColor].CGColor;[boxView.layer addSublayer:scanLayer];// 開始掃描
    [session startRunning];
}-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
? ??for (id objects in metadataObjects) {

? ? ? ? // 判斷檢測到的對象類型

? ? ? ? if (![objects isKindOfClass:[AVMetadataMachineReadableCodeObject class]]) {

? ? ? ? ? ? return;

? ? ? ? }

? ? ? ? // 轉換對象坐標

? ? ? ? AVMetadataMachineReadableCodeObject *obj = (AVMetadataMachineReadableCodeObject *)[preViewLayer transformedMetadataObjectForMetadataObject:objects];

? ? ? ? // 判斷掃描范圍

? ? ? ? if (!CGRectContainsRect(self.boxView.frame, obj.bounds)) {

? ? ? ? ? ? continue;

     }

 

? ? ? ? // 設置代理

     ?if ([self.delegate respondsToSelector:@selector(scanQrcodeWithNString:)]) {

? ? ? ? ? ? [self.delegate scanQrcodeWithNString:obj.stringValue];

     }?

     // 停止掃描

    ?[self.session stopRunning];

? ? ? ? // 移除CADisplayLink對象

? ? ? ? [self.link removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];

? ? ? ? self.link = nil;

? ? }


}-(void)updataFrame {CGRect frame = self.scanLayer.frame;if (self.scanLayer.frame.origin.y > self.boxView.frame.size.height) {frame.origin.y = -20;self.scanLayer.frame = frame;}else{frame.origin.y += 3;self.scanLayer.frame = frame;}}-(void)viewDidDisappear:(BOOL)animated{[super viewDidDisappear:animated];// 記得釋放CADisplayLink對象if (self.link != nil) {[self.link invalidate];self.link = nil;} }// 返回上一個界面 -(void)goBack {[self.navigationController popViewControllerAnimated:YES]; }// 二維碼掃描完成 -(void)doneClick {// 設置代理if ([self.delegate respondsToSelector:@selector(scanQrcodeWithNString:)]) {[self.delegate scanQrcodeWithNString:self.string];}[self.navigationController popToRootViewControllerAnimated:YES]; } @end

?

?

?

?

?

?

?

轉載于:https://www.cnblogs.com/Mr-Ygs/p/4904710.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/397382.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/397382.shtml
英文地址,請注明出處:http://en.pswp.cn/news/397382.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

有符號位和無符號位。——int8疑問有感

學習go語言的數據類型&#xff0c;看見int、int8、int16很是疑惑&#xff0c;int8是什么意思&#xff1f;查詢資料進行綜合解釋大概如下&#xff1a; Int8是有符號位8位整形&#xff08;-128到127&#xff09;&#xff0c;隨即產生疑惑&#xff0c;為什么負數可表示到-128&…

html幫助文檔亂碼,使用doxygen生成的幫助文檔,中文出現亂碼的問題

今天使用doxygen工具生成幫助文檔發現中文注釋都是亂碼。然后根據網上的要求把Exper>>Input>>INPUT_ENCODING&#xff1a;(輸入文件的編碼) UTF-8 改成 GBK 或者 GB2312Exper>>HTML>>CHM_INDEX_ENCODING&#xff1a;(輸出文件的編碼) UTF-8 改成 GBK 或…

Java并發編程--理解ThreadLocal

另一篇博文&#xff1a;Hibernet中的ThreadLocal使用 http://www.cnblogs.com/gnivor/p/4440776.html 本文參考&#xff1a;http://blog.csdn.net/lufeng20/article/details/24314381http://www.cnblogs.com/chenying99/articles/3405161.html ThreadLocal類接口很簡單&#xf…

delphi Post數據到網頁

varhttp: TIdHttp;sendtoserver: TStringStream;str: string; beginhttp : TIdHttp.Create(); // 創建http.HandleRedirects : True; // 允許轉頭http.ReadTimeout : 3000; …

python之路——迭代器與生成器

要了解for循環是怎么回事兒&#xff0c;咱們還是要從代碼的角度出發。 首先&#xff0c;我們對一個列表進行for循環。 for i in [1,2,3,4]: print(i) 上面這段代碼肯定是沒有問題的&#xff0c;但是我們換一種情況&#xff0c;來循環一個數字1234試試 for i in 1234print(i) 結…

HTML頁面顯示透視效果,html – CSS – 對背景圖像的“敲除”/透視效果

我認為這里的想法是圖像必須足夠大,以覆蓋網頁或至少父母div ..然后,您可以將圖像應用于容器和’inner’div的背景.覆蓋可以通過偽元素而不是單獨的div來實現.修訂結構 –.bck {position: relative;height: 800px;width: 100%;background:url(http://webneel.com/wallpaper/sit…

DFS分布式文件系統--管理篇

DFS分布式文件系統--管理篇參考文檔&#xff1a;淺談DFS分布式文件系統DFS 命名空間 和 DFS 復制概述續DFS分布式文件系統--基礎篇DFS分布式文件系統--部署篇添加命名空間服務器&#xff08;添加第二臺命名空間服務器 NameSrv02)成功后如下圖&#xff1a;“從顯示區域隱藏命名空…

Linux 0-1 修改主機名及IP地址

1.修改主機名 hostname 查看主機名 vi /etc/sysconfig/network 修改hostname主機名 vi /etc/hosts 修改127.0.1 主機名 service network restart #/etc/hosts 在域名解析時優先于DNS服務器2.IP地址 ifconfig 查看目前網絡卡信息 cd /etc/sysconfig/network-scripts ls查看…

html漸變顏色代碼表,漸變顏色代碼表

漸變顏色代碼表2020-12-24素材&#xff1a;網絡 編輯&#xff1a;唔爾灬#000000#2F0000#600030#460046#28004D#272727#4D0000#820041#5E005E#3A006F#3C3C3C#600000#9F0050#750075#4B0091#4F4F4F#750000#BF0060#930093#5B00AE#5B5B5B#930000#D9006C#AE00AE#6F00D2#6C6C6C#AE0000…

js貪心算法---背包問題

/** param {Object} capacity 背包容量 6* param {Object} weights 物品重量 [2,3,4]* param {Object} values 物品價值 [3,4,5]*///貪心算法&#xff0c;只能算&#xff0c;可以分割的物品&#xff0c;如果不能分割物品&#xff0c;只能得到近似解&#xff0c;不分割物品&…

Spring利用JDBCTemplate實現批量插入和返回id

1、先介紹一下java.sql.Connection接口提供的三個在執行插入語句后可取的自動生成的主鍵的方法&#xff1a; //第一個是 PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException; 其中autoGenerateKeys 有兩個可選值&#xff1a;Stat…

jsp壓縮html,使用HtmlCompressor壓縮JSP編譯的Html代碼

HtmlCompressor 能夠刪除多余的HTML代碼。它提供多種方法&#xff1a;刪除無用的空行、刪除注釋以及刪除無用的表格等等&#xff0c;簡單而有效。在Java代碼中可以這樣使用&#xff1a;String html getHtml(); //需要處理的Html代碼HtmlCompressor compressor new HtmlCompre…

LVS負載均衡(3)——LVS工作模式與工作原理

LVS介紹及工作原理1. LVS 介紹LVS,Linux Virtual Server 的簡寫&#xff0c;意即 Linux 虛擬服務器&#xff0c;是一個虛擬的服務器集群系統&#xff0c;可以在 UNIX/Linux 平臺下實現負載均衡集群功能。文章&#xff1a;LVS項目介紹LVS集群體系結構LVS集群的IP負載均衡技術LVS…

保留凸性的方式:一個凸函數在一個隨機變量上的期望仍然是凸函數

設函數 gg 是實數范圍內的一個凸函數&#xff0c;DD 是一個隨機變量&#xff0c; 那么函數 GEDg(y?D)GEDg(y?D) 仍然是一個凸函數。 證明&#xff1a;記 θθθθ, yy 與 yy 是任意兩個數 ≥θG(y)θG(y)θEDg(y?D)θEDg(y?D)ED[θg(y?D)θ(gy?D)]ED[g(θyθy?D)]G(θyθ…

MyBatis入門(二)---一對一,一對多

一、創建數據庫表 1.1、創建數據表同時插入數據 /* SQLyog Enterprise v12.09 (64 bit) MySQL - 5.6.27-log : Database - mybatis ********************************************************************* *//*!40101 SET NAMES utf8 */;/*!40101 SET SQL_MODE*/;/*!40014 SE…

零基礎學Java的10個方法

2019獨角獸企業重金招聘Python工程師標準>>> 版權聲明&#xff1a;本文為北京尚學堂原創文章&#xff0c;未經允許不得轉載。? 零基礎學Java只要方法得當&#xff0c;依然有機會學習好Java編程。 但作為初學者可以通過制定一些合理清晰的學習計劃。 在幫你屢清楚思…

html 轉換為cshtml,使用Html而不是csHtml

我想使用純HTML頁面而不是使用MVC .net的cshtml . 但是當我通過右鍵單擊索引添加視圖時&#xff0c;我只能看到兩個選項 .public class HomeController : Controller{//// GET: /Home/public ActionResult Index(){return View();}}Cshtml(剃刀)Aspx論壇但仍無濟于事 . 我仍然沒…

scp windows 和 linux 遠程復制 (雙向)

一下命令在cmd中 從w -> l : scp D:\a.txt root192.168.2.113:/home/a 從l -> w: scp root192.168.2.113:/home/aaa d:/b.txt 按說在Linux中也可以&#xff0c;但是不知道怎么的只有在winodws上行&#xff0c;在linux上就會報 ssh: connect to host 192.168.2.157 port 2…

北京尚學堂|程序員的智慧

2019獨角獸企業重金招聘Python工程師標準>>> 版權聲明&#xff1a;本文為北京尚學堂原創文章&#xff0c;未經允許不得轉載。 編程是一種創造性的工作&#xff0c;是一門藝術。精通任何一門藝術&#xff0c;都需要很多的練習和領悟&#xff0c;所以這里提出的“智慧…

翼城中學2021高考成績查詢入口,2021年臨汾中考分數線查詢(4)

臨汾2021年中考分數線查詢 2021臨汾中考錄取分數線 19年臨汾中考各校錄取分數線 臨汾各高中錄取分數線 臨汾2021中考錄取線查詢 中考信息網提供2021臨汾中考分數線查詢信息。臨汾中考錄取分數線預計7月初公布&#xff0c;屆時考生可登陸臨汾招生考試網官網查看分數線情況。2…