iOS原生封裝二維碼、條形碼掃描工具庆冕;生成康吵、識(shí)別(彩色)二維碼、條形碼圖片

二維碼掃描在App中很常見(jiàn)的功能愧杯,之前都是用三方工具Zing涎才、ZBar鞋既。后來(lái)Apple的AVFoundation也支持二維碼掃描力九、生成,而且效率比三方庫(kù)還要高邑闺。我把它封裝成一個(gè)工具跌前,這樣使用起來(lái)十分方便,同時(shí)還封裝了掃描視圖陡舅,在工程中增加掃描更加快捷抵乓。

主要使用AVCaptureSession鏈接攝像頭進(jìn)行采集信息
Coding~

//初始化鏈接對(duì)象
self.session = [[AVCaptureSession alloc]init];
//高質(zhì)量采集率
[self.session setSessionPreset:AVCaptureSessionPresetHigh];
//獲取攝像設(shè)備
self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
//創(chuàng)建輸入流
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];
//添加輸入流
if ([self.session canAddInput:input]) {
    [self.session addInput:input];
}
//創(chuàng)建輸出流
self.output = [[AVCaptureMetadataOutput alloc] init];
//設(shè)置代理在主線程里刷新(Tip:如果封裝的類不是單利或者全局變量,代理AVCaptureMetadataOutputObjectsDelegated不會(huì)被調(diào)用)
[self.output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
//添加輸出流
if ([self.session canAddOutput:self.output]) {
    [self.session addOutput:self.output];
}
//設(shè)置掃碼支持的編碼格式靶衍,Tip:必須在添加輸出流之后
if ([self.output availableMetadataObjectTypes].count) {
    if (scanType == ZHBarScanTypeQRCode) {
        self.output.metadataObjectTypes = @[AVMetadataObjectTypeQRCode];
    } else if (scanType == ZHBarScanTypeBarCode) {
        self.output.metadataObjectTypes = @[AVMetadataObjectTypeEAN13Code,
                                            AVMetadataObjectTypeEAN8Code,
                                            AVMetadataObjectTypeCode128Code];
    } else {
        self.output.metadataObjectTypes = @[AVMetadataObjectTypeQRCode,
                                            AVMetadataObjectTypeEAN13Code,
                                            AVMetadataObjectTypeEAN8Code,
                                            AVMetadataObjectTypeCode128Code];
    }
}
//設(shè)置有效的掃描區(qū)域灾炭,Tip:rectOfInterest是比值,默認(rèn)為CGRectMake(0, 0, 1, 1)
/* 手動(dòng)計(jì)算
 計(jì)算為CGRectMake(y1/h, x1/w, h1/h, w1/w);
 y1,x1,h1,w1為掃描區(qū)域的frame颅眶,h,w是layer視圖的寬高
 手動(dòng)計(jì)算要在session運(yùn)行前設(shè)置
 */

/* 自動(dòng)轉(zhuǎn)換
 - (CGRect)metadataOutputRectOfInterestForRect:(CGRect)rectInLayerCoordinatesl;
 這個(gè)方法可以把掃描區(qū)域的frame轉(zhuǎn)成rectOfInterest的坐標(biāo)系
 這個(gè)方法必須在session運(yùn)行后設(shè)置
 */

//如果傳入的scanArea的寬不大于1蜈出,說(shuō)明是手動(dòng)計(jì)算
if (scanRect.size.width <= 1) {
    self.output.rectOfInterest = scanRect;
}
//創(chuàng)建相機(jī)渲染層
self.layer = [AVCaptureVideoPreviewLayer layerWithSession:self.session];
self.layer.videoGravity = AVLayerVideoGravityResizeAspectFill;
self.layer.frame = layerView.layer.bounds;
[layerView.layer insertSublayer:self.layer atIndex:0];

[ZHBarTool requestCameraAuthorizedResult:^(BOOL granted) {
    if (granted) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.session startRunning];
            self.isAvailable = YES;
            self.scanInterval = self.scanInterval ? self.scanInterval : 2;
            //如果傳入的scanArea的寬大于1,調(diào)用系統(tǒng)方法轉(zhuǎn)換
            if (scanRect.size.width > 1) {
                self.scanRect = scanRect;
                CGRect rectOfInterest = [self.layer metadataOutputRectOfInterestForRect:scanRect];
                self.output.rectOfInterest = rectOfInterest;
            }
        });
    } else {
        if ([self.delegate respondsToSelector:@selector(ZHBarAuthorizedCameraFailed)]) {
            [self.delegate ZHBarAuthorizedCameraFailed];
        }
        if (self.authorizedCameraFailed) {
            self.authorizedCameraFailed();
        }
    }
}];

注意點(diǎn):

有效的掃描區(qū)域:rectOfInterest涛酗。這是個(gè)比值铡原,而且坐標(biāo)系和我們平常開(kāi)發(fā)使用的不一樣偷厦,計(jì)算時(shí)需要轉(zhuǎn)化,不過(guò)系統(tǒng)給我們提供了方法

- (CGRect)metadataOutputRectOfInterestForRect:(CGRect)rectInLayerCoordinatesl;

可以轉(zhuǎn)化我們熟悉的坐標(biāo)系下的frame為rectOfInterest需要的坐標(biāo)燕刻,但使用這個(gè)方法必須在session啟動(dòng)之后設(shè)置只泼。

代理:

- (void)captureOutput:(AVCaptureOutput *)output didOutputMetadataObjects:(NSArray<__kindof AVMetadataObject *> *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
AVMetadataMachineReadableCodeObject *object = [metadataObjects objectAtIndex:0];
NSString *obj = [object stringValue];
}

二維碼條形碼生成

主要使用過(guò)濾器CIFilter
//二維碼過(guò)濾器
CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
/條形碼過(guò)濾器
CIFilter *filter = [CIFilter filterWithName:@"CICode128BarcodeGenerator"];

解析二維碼圖片

NSString *url = nil;
//初始化一個(gè)監(jiān)測(cè)器
CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{CIDetectorAccuracy:CIDetectorAccuracyHigh}];
//監(jiān)測(cè)到的結(jié)果數(shù)組
NSArray *features = [detector featuresInImage:[CIImage imageWithCGImage:aImage.CGImage]];
if (features.count >=1) {
    //結(jié)果對(duì)象
    CIQRCodeFeature *feature = [features objectAtIndex:0];
    NSString *result = feature.messageString;
    url = result;
}

解析條形碼圖片

很遺憾╮(╯_╰)原生還不支持解析條形碼圖片,如果有需要的話只能使用三方庫(kù)了卵洗。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末请唱,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子过蹂,更是在濱河造成了極大的恐慌籍滴,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件榴啸,死亡現(xiàn)場(chǎng)離奇詭異孽惰,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)鸥印,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門勋功,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人库说,你說(shuō)我怎么就攤上這事狂鞋。” “怎么了潜的?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵骚揍,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我啰挪,道長(zhǎng)信不,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任亡呵,我火速辦了婚禮抽活,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘锰什。我一直安慰自己下硕,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布汁胆。 她就那樣靜靜地躺著梭姓,像睡著了一般。 火紅的嫁衣襯著肌膚如雪嫩码。 梳的紋絲不亂的頭發(fā)上誉尖,一...
    開(kāi)封第一講書(shū)人閱讀 51,443評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音谢谦,去河邊找鬼释牺。 笑死萝衩,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的没咙。 我是一名探鬼主播猩谊,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼祭刚!你這毒婦竟也來(lái)了牌捷?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤涡驮,失蹤者是張志新(化名)和其女友劉穎暗甥,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體捉捅,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡撤防,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了棒口。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片寄月。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖无牵,靈堂內(nèi)的尸體忽然破棺而出漾肮,到底是詐尸還是另有隱情,我是刑警寧澤茎毁,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布克懊,位于F島的核電站,受9級(jí)特大地震影響七蜘,放射性物質(zhì)發(fā)生泄漏谭溉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一崔梗、第九天 我趴在偏房一處隱蔽的房頂上張望夜只。 院中可真熱鬧垒在,春花似錦蒜魄、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至踢关,卻和暖如春伞鲫,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背签舞。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工秕脓, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留柒瓣,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓吠架,卻偏偏與公主長(zhǎng)得像芙贫,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子傍药,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

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

  • 關(guān)于二維碼(或者條形碼,以下歸類簡(jiǎn)稱二維碼)掃描和生成的,我相信網(wǎng)絡(luò)上相關(guān)的文章層數(shù)不窮,但是,大部分都是直接粘貼...
    FR_Zhang閱讀 6,655評(píng)論 10 41
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)磺平、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,103評(píng)論 4 62
  • **申明** 由于用簡(jiǎn)書(shū)寫(xiě)代碼有很多代碼會(huì)無(wú)緣無(wú)故消失掉拐辽,所以才用了圖片的方式 *以下重新補(bǔ)發(fā)鏈接* [后盾網(wǎng)](...
    Jiang鋒時(shí)刻閱讀 281評(píng)論 0 0
  • 文 / IDO老徐原創(chuàng)文章俱诸,禁止轉(zhuǎn)載菠劝;轉(zhuǎn)發(fā)、分享隨意睁搭。 繼上次分享簡(jiǎn)歷&面試后闸英,今天繼續(xù)分享面試話題分享IDO老徐...
    IDO老徐閱讀 2,346評(píng)論 11 20
  • 話說(shuō)這李澤言雖然心里犯著嘀咕,但是還是如約大半夜來(lái)到了老師房間前介袜。 正要敲門呢甫何,房間里傳來(lái)一個(gè)聲音,進(jìn)來(lái)吧遇伞,門沒(méi)鎖...
    十月sep閱讀 904評(píng)論 1 1