iOS開發(fā)-二維碼掃描和應用跳轉(zhuǎn)

序言

前面我們已經(jīng)調(diào)到過怎么制作二維碼,在我們能夠生成二維碼之后溜畅,如何對二維碼進行掃描呢憋活?

在iOS7之前铝耻,大部分應用中使用的二維碼掃描是第三方的掃描框架,例如ZXing或者ZBar贞远。使用時集成麻煩畴博,出錯也不方便調(diào)試。在iOS7之后蓝仲,蘋果自身提供了二維碼的掃描功能俱病,從效率上來說,原生的二維碼遠高于這些第三方框架袱结。本文講解如何使用原生框架實現(xiàn)二維碼掃描功能亮隙,并且進行掃描后的項目跳轉(zhuǎn)。
ps:本期的源代碼會在文章結尾給出鏈接


掃描相關類

二維碼掃描需要獲取攝像頭并讀取照片信息垢夹,因此我們需要導入系統(tǒng)的AVFoundation框架溢吻,創(chuàng)建視頻會話。我們需要用到一下幾個類:

  • AVCaptureSession 會話對象棚饵。此類作為硬件設備輸入輸出信息的橋梁煤裙,承擔實時獲取設備數(shù)據(jù)的責任
  • AVCaptureDeviceInput 設備輸入類。這個類用來表示輸入數(shù)據(jù)的硬件設備噪漾,配置抽象設備的port
  • AVCaptureMetadataOutput 輸出類硼砰。這個支持二維碼、條形碼等圖像數(shù)據(jù)的識別
  • AVCaptureVideoPreviewLayer 圖層類欣硼。用來快速呈現(xiàn)攝像頭獲取的原始數(shù)據(jù)
    二維碼掃描功能的實現(xiàn)步驟是創(chuàng)建好會話對象题翰,用來獲取從硬件設備輸入的數(shù)據(jù),并實時顯示在界面上诈胜。在掃描到相應圖像數(shù)據(jù)的時候豹障,通過AVCaptureVideoPreviewLayer類型進行返回

應用跳轉(zhuǎn)

在使用第三方登陸焦匈、分享sdk的時候,我們的項目會在本機安裝有目標平臺的應用的情況下進行應用跳轉(zhuǎn)缓熟,并且傳遞信息過去摔笤。這在沙盒機制下的iOS應用而言,理應是不符合規(guī)則的垦写。但是吕世,iOS SDK給我們提供了一個叫做url scheme的機制來實現(xiàn)這個功能梯投。

url scheme讓我們可以像使用Safari打開網(wǎng)頁的方式跳轉(zhuǎn)到其他應用中,并使用類似網(wǎng)絡請求的GET請求的參數(shù)拼湊方式來在不同應用之間傳遞數(shù)據(jù)分蓖。

使用url scheme的第一步是在項目的info.plist文件中添加新row尔艇,命名為URL types


1.png

展開新增的字典,我們修改其中的URL Identifier以及新增加一個字段
URL Schemes漓帚。
Identifier用來跳轉(zhuǎn)后午磁,讓跳轉(zhuǎn)應用識別從哪里跳轉(zhuǎn)過來的,我們可以設置為bundleID反轉(zhuǎn)昧辽,來確保其特殊性登颓。
URL Schemes是一個數(shù)組搅荞,我們將在這個數(shù)組里面自定義自己的url schemes咕痛,這里我們填寫應用名喇嘱。最終效果如下:


9A8E2746-D1D9-4BC2-81FE-23E13C5EF202.png

接著,我們就可以在其他應用中通過openURL:方法打開我們的app腔丧。


二維碼掃描

二維碼掃描的步驟:
1作烟、創(chuàng)建設備會話對象,用來設置設備數(shù)據(jù)輸入
2衣厘、獲取攝像頭压恒,并且將攝像頭對象加入當前會話中
3怖亭、實時獲取攝像頭原始數(shù)據(jù)顯示在屏幕上
4坤检、掃描到二維碼/條形碼數(shù)據(jù)期吓,通過協(xié)議方法回調(diào)

  • 會話對象AVCaptureSession的創(chuàng)建
    _session = [AVCaptureSession new];
    [_session setSessionPreset: AVCaptureSessionPresetHigh]; //高質(zhì)量采集
    [self setupIODevice];

  • setupIODevice方法中懶加載方式創(chuàng)建輸入對象和輸出對象讨勤,注意必須在輸出數(shù)據(jù)對象加入到當前會話后才能設置識別的數(shù)據(jù)格式。這里設置為掃描二維碼以及條形碼
    [_session addInput: self.input];
    [_session addOutput: self.output];
    _output.metadataObjectTypes = @[AVMetadataObjectTypeQRCode, AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code];

  • 創(chuàng)建AVCaptureMetadataOutput設置好掃描成功回調(diào)代理以及回調(diào)線程
    _output = [AVCaptureMetadataOutput new];
    [_output setMetadataObjectsDelegate: self queue: dispatch_get_main_queue()];

  • 創(chuàng)建AVCaptureDeviceInput輸入設備為手機攝像頭
    AVCaptureDevice * device = [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeVideo];
    _input = [AVCaptureDeviceInput deviceInputWithDevice: device error: nil];

  • 創(chuàng)建AVCaptureVideoPreviewLayer對象來實時獲取攝像頭圖像谱姓,我們需要調(diào)用[self.view addSubview: self.scanView]把攝像頭獲取的圖像實時展示在屏幕上
    _scanView = [AVCaptureVideoPreviewLayer layerWithSession: self.session];
    _scanView.videoGravity = AVLayerVideoGravityResizeAspectFill;
    _scanView.frame = self.bounds;

  • 實現(xiàn)captureOutput: didOutputMetadataObjects: fromConnection:來獲取掃描得到的數(shù)據(jù)刨晴。回調(diào)參數(shù)metadataObjects中存放了掃描結果茄靠,我們需要先判斷這個數(shù)組的數(shù)據(jù)個數(shù)不為0再執(zhí)行下面的代碼:
    [self stop];
    AVMetadataMachineReadableCodeObject * metadataObject = metadataObjects[0];
    if ([self.delegate respondsToSelector: @selector(scanView:codeInfo:)]) {
    [self.delegate scanView: self codeInfo: metadataObject.stringValue];
    [self removeFromSuperview];
    } else {
    [[NSNotificationCenter defaultCenter] postNotificationName: LXDSuccessScanQRCodeNotification object: self userInfo: @{ LXDScanQRCodeMessageKey: metadataObject.stringValue }];


讀取二維碼信息進行應用跳轉(zhuǎn)

首先要說明的是蝶桶,二維碼并非一定要存儲應用的url scheme。例如公眾號的二維碼脐雪,雖然不知道是怎樣的數(shù)據(jù)存儲恢共,但肯定不是應用跳轉(zhuǎn)』裱可以給自己的應用指定一個二維碼數(shù)據(jù)規(guī)則拐袜,例如支付寶付款掃描是讀取商品的ID、價格等信息蹬铺,然后進行頁面跳轉(zhuǎn)付款甜攀。
這里我們使用上面設置的url scheme琐馆,我們通過制作二維碼方法來定制一個存儲應用跳轉(zhuǎn)信息的二維碼恒序,通過下面的代理創(chuàng)建一個存儲url scheme(使用url scheme的時候要注意在后面加上://后才能使用openURL進行跳轉(zhuǎn))的二維碼,這一步應該放到模擬器上面生成

  • (IBAction)createBarcode:(id)sender
    {
    UIImage * image = [UIImage imageOfQRFromURL: @"LXDDrawLosts://" codeSize: 160.f red: 123 green: 189 blue: 229 insertImage: nil];
    CGSize size = image.size;
    UIImageView * imageView = [[UIImageView alloc] initWithFrame: ((CGRect){(CGPointZero), (size)})];
    imageView.center = self.view.center;
    imageView.image = image;
    [self.view addSubview: imageView];
    }

創(chuàng)建二維碼掃描控制器滋饲,然后對我們生成的二維碼進行掃描(這一步要在真機上面完成喊巍,上面url scheme的應用應當通過xcode安裝在手機上,才能完成跳轉(zhuǎn))

LXDScanCodeController * scanCodeController = [LXDScanCodeController scanCodeController];
scanCodeController.scanDelegate = self;
[self.navigationController pushViewController: scanCodeController animated: YES];

掃描成功后判斷是否可以打開跳轉(zhuǎn)呵曹,如果你的應用有一套二維碼數(shù)據(jù)存儲的規(guī)則何暮,那么在不能跳轉(zhuǎn)的時候應該按照這套規(guī)則解析數(shù)據(jù)。這里我直接在無法跳轉(zhuǎn)的情況下顯示警告框告訴用戶無法解析二維碼:

NSURL ** * url = [NSURL URLWithString: codeInfo];
if ([[UIApplication sharedApplication] canOpenURL: url]) {
[[UIApplication sharedApplication] openURL: url];
} else {
UIAlertView ** * alertView = [[UIAlertView alloc] initWithTitle: @"警告" message: [NSString stringWithFormat: @"%@:%@", @"無法解析的二維碼", codeInfo] delegate: nil cancelButtonTitle: @"確定" otherButtonTitles: nil];
[alertView show];
}

按照上面的步驟進行的話砍聊,那么在你掃完二維碼之后贰军,你的手機就會跳轉(zhuǎn)到剛才設置url scheme的應用中。


掃描優(yōu)化

上面已經(jīng)完成了二維碼的掃描功能實現(xiàn)俯树,但是現(xiàn)在你會發(fā)現(xiàn)我們在使用上面代碼進行掃描的時候贰盗,整個屏幕都是掃描范圍,這樣會影響掃描的準確性以及我們調(diào)整掃描范圍的難度陋率。
蘋果提供了一種方式讓我們規(guī)定掃描范圍:在AVCaptureMetadataOutput中有一個叫做rectOfInterest的CGRect類型屬性秽晚,這個屬性用來限制掃描范圍。
這個屬性的每一個值取值范圍在0~1之間菩浙,代表的是對應軸上的比例大小。最開始我以為這個是以左上角為原點陆淀,后來設置為CGRectMake(0.3, 0.35, 0.4, 0.3)發(fā)現(xiàn)和預期的不一樣先嬉,因為這個屬性是以屏幕右上角為坐標原點,并且寬高的順序要對換過來

1.jpg

如圖所示浸剩,由于坐標系的不同鳄袍,原本CGRectMake(0.3, 0.35, 0.4, 0.3)到了新坐標系中就變成了CGRectMake(0.35, 0.3, 0.3, 0.4)吏恭。那么大家設置成新的掃描范圍之后,重新運行掃描程序哀九,看看效果——然而搅幅,我們發(fā)現(xiàn)并不能掃描成功,這是因為這個掃描區(qū)域不僅僅是坐標系原點發(fā)生了改變息裸。如下圖所示

1.png

按照上面CGRect的設置沪编,我是想要把掃描范圍控制在屏幕x軸上面0.3-0.7,y軸上0.35-0.65之間的范圍访圃。但是在這個屬性中相嵌,width和height分別表示的是在rectOfInterest坐標中掃描矩形右下角的坐標點位置。因此批糟,這個掃描范圍應該是CGRectMake(0.35, 0.3, 0.65, 0.7)捏雌。除了設置好掃描范圍之內(nèi),我們還可以仿照微信的掃描纬傲,給非掃描范圍加上一層半透明的黑色layer


應用傳值

前面說過,url scheme不僅僅支持應用跳轉(zhuǎn)算墨,它還支持使用類似get請求的方式在應用間傳值汁雷。上面跳轉(zhuǎn)的url scheme是LXDDrawLosts://,那么類似get請求挖藏,我們在這個字符串后面加上一個?表示區(qū)分開參數(shù)和應用id厢漩,使用&分隔不同參數(shù),然后后面按照字段名=屬性值的方式拼湊鏈接宵膨。
比如炸宵,假設這是一個即時通訊app,那么我可以制定這樣的一個跳轉(zhuǎn)參數(shù)規(guī)則:

  • method 表示操作類型
  • userId 用戶id
  • title 分享標題
  • message 分享消息
  • link_url 分享鏈接

那么土全,如果傳入的是
LXDDrawLosts://?method=addFriends&userId=10086
這可能代表的是掃描后添加id為10086的新好友涯曲。

又比如
LXDDrawLosts://?method=shareMessage&title=分享測試&message=這是林欣達的分享測試&link_url=http://www.reibang.com/users/0cf7d455eb9e/latest_articles
這代表分享信息到你的app中。這些都是我們自己的應用可以制定的規(guī)則拨黔,如果有興趣绰沥,可以新浪微博開放平臺或者騰訊開放平臺,他們的文檔中應該有url scheme的傳值標準零截。

說完了通過url scheme傳入?yún)?shù)后秃臣,怎么把這些參數(shù)取出來呢哪工?AppDelegate中提供了application:openURL: sourceApplication: annotation:方法讓我們可以取出傳入的值弧哎。
在我們通過url scheme跳轉(zhuǎn)到本應用的時候,這個方法就會被系統(tǒng)調(diào)用偎捎。其中序攘,有兩個重要的參數(shù)需要我們知道

  • sourceApplication 這個字符串保存了跳轉(zhuǎn)方app的url Identifier,就是上文中除了url scheme以外的另一個字段
  • url 這個鏈接中存儲了跳轉(zhuǎn)的url scheme以及參數(shù)列表丈牢,我們通過[url scheme]方法獲取前者瞄沙;用[url query]方法獲取?之后的參數(shù)列表,然后使用字符串的分隔方法把這些數(shù)據(jù)讀取出來

單純的二維碼數(shù)據(jù)并沒有過于強大的功能,但結合了url scheme的跳轉(zhuǎn)機制后遂铡,二維碼能夠幫助我們的應用獲得更加強大的能力扒接,使得我們的應用之間有了更多聯(lián)系。

文集:iOS開發(fā)

本文demo:二維碼掃描集成
轉(zhuǎn)載表明鏈接:http://sindrilin.com/ios-dev/2015/11/01/二維碼掃描和應用跳轉(zhuǎn).html

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末碱呼,一起剝皮案震驚了整個濱河市宗侦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌姑裂,老刑警劉巖男旗,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異茴厉,居然都是意外死亡,警方通過查閱死者的電腦和手機怀酷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進店門而账,熙熙樓的掌柜王于貴愁眉苦臉地迎上來泞辐,“玉大人,你說我怎么就攤上這事咐吼。” “怎么了厢塘?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵晚碾,是天一觀的道長喂急。 經(jīng)常有香客問我,道長廊移,這世上最難降的妖魔是什么狡孔? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮殃恒,結果婚禮上辱揭,老公的妹妹穿的比我還像新娘。我一直安慰自己侯繁,他們只是感情好泡躯,可當我...
    茶點故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布丽焊。 她就那樣靜靜地躺著咕别,像睡著了一般惰拱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上偿短,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天昔逗,我揣著相機與錄音,去河邊找鬼勾怒。 笑死笔链,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的鉴扫。 我是一名探鬼主播幔妨,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼谍椅,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了锁施?” 一聲冷哼從身側(cè)響起杖们,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤摘完,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后孝治,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體审磁,經(jīng)...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡态蒂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年钾恢,在試婚紗的時候發(fā)現(xiàn)自己被綠了鸳址。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡募舟,死狀恐怖闻察,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情呢灶,我是刑警寧澤钉嘹,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站缨睡,受9級特大地震影響陈辱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜沛贪,卻給世界環(huán)境...
    茶點故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一利赋、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧中燥,春花似錦塘偎、人聲如沸幽纷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽收恢。三九已至祭往,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間驮肉,已是汗流浹背已骇。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留卵渴,地道東北人鲤竹。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓辛藻,卻偏偏與公主長得像,于是被迫代替她去往敵國和親吱肌。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,573評論 2 359

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理坟瓢,服務發(fā)現(xiàn),斷路器折联,智...
    卡卡羅2017閱讀 134,702評論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,290評論 25 707
  • 一诚镰、前言 最近在做一個關于掃描二維碼簽到的小東西祥款,所以還是上來寫一篇關于二維碼的文章月杉,網(wǎng)上也有一些掃描二維碼的框架...
    kim逸云閱讀 4,421評論 2 8
  • 今天情緒失控在知道回婆婆家吃飯的時候蛙酪。 我太Tmd不想去婆婆家吃飯!昨天前面忙的回家晚桂塞,到家后兒子和愛人才從婆婆家...
    云中看花閱讀 174評論 0 0
  • 我一直覺得自己不是一個多么幸運的人阁危,但比起那些真正不幸的人,我覺得我的不幸也算不得什么欲芹。我現(xiàn)在不是還活的好好的嗎吟吝?...
    菀薇閱讀 669評論 0 2