iOS開發(fā)_原生二維碼生成與讀取

今天有時間整理下原生的二維碼的生成與讀取。

準備工作

  • 導入<CoreImage/CoreImage.h>干旁,生成二維碼用
  • 導入<AVFoundation/AVFoundation.h>炮沐,讀取二維碼用
  • 協(xié)議AVCaptureMetadataOutputObjectsDelegate,這是有關(guān)攝像設(shè)備輸出的相關(guān)代理
  • 注意:掃描二維碼的時候换薄,要在info.plist文件中添加字段鲜戒,否則會崩潰(iOS10之后的隱私權(quán)限問題)

    <key>NSPhotoLibraryUsageDescription</key>
    <string>App需要您的同意,才能訪問相冊</string>

    <key>NSCameraUsageDescription</key>
    <string>App需要您的同意,才能訪問相機</string>

二維碼的生成

1.生成二維碼的步驟:

1)導入CoreImage框架
2)通過濾鏡CIFilter生成二維碼
代碼如下
調(diào)用下方根據(jù)字符串生成二維碼的方法即可獲得二維碼
 // 生成二維碼
- (UIImage *)createImageWithString:(NSString *)string{

// 1.實例化二維碼濾鏡
CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
// 2.恢復濾鏡的默認屬性(因為濾鏡可能保存上一次的屬性)
[filter setDefaults];

// 3.講字符串轉(zhuǎn)換為NSData
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];*

// 4.通過KVO設(shè)置濾鏡inputMessage數(shù)據(jù)
[filter setValue:data forKey:@"inputMessage"];

// 5.通過了濾鏡輸出的圖像
CIImage *outputImage = [filter outputImage];

// 6.因為生成的二維碼模糊遏餐,所以通過createNonInterpolatedUIImageFormCIImage:outputImage來獲得高清的二維碼圖片

UIImage *image = [self getErWeiMaImageFormCIImage:outputImage withSize:200];

return image;   
}

// 獲取高清二維碼圖片
- (UIImage *)getErWeiMaImageFormCIImage:(CIImage *)image withSize:(CGFloat) size {
CGRect extent = CGRectIntegral(image.extent);
CGFloat scale = MIN(size/CGRectGetWidth(extent), size/CGRectGetHeight(extent));

// 1.創(chuàng)建bitmap;
size_t width = CGRectGetWidth(extent) * scale;
size_t height = CGRectGetHeight(extent) * scale;
CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray();
CGContextRef bitmapRef = CGBitmapContextCreate(nil, width, height, 8, 0, cs, (CGBitmapInfo)kCGImageAlphaNone);
CIContext *context = [CIContext contextWithOptions:nil];
CGImageRef bitmapImage = [context createCGImage:image fromRect:extent];
CGContextSetInterpolationQuality(bitmapRef, kCGInterpolationNone);
CGContextScaleCTM(bitmapRef, scale, scale);
CGContextDrawImage(bitmapRef, extent, bitmapImage);

// 2.保存bitmap到圖片
CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);
CGContextRelease(bitmapRef);
CGImageRelease(bitmapImage);
return [UIImage imageWithCGImage:scaledImage];
}
運行結(jié)果

[圖片上傳失敗...(image-bbce1-1542166399362)]


????????????我是可愛的分割線????????????


二維碼的生成還是比較簡單的失都,下面讓我們來看下二維碼的掃描


????????????我是可愛的分割線????????????


二維碼的讀取

1.讀取二維碼的步驟:

1)讀取二維碼需要導入AVFoundation框架(上方準備工作的時候已經(jīng)說了)
2)利用相機識別二維碼中的內(nèi)容(只能是真機)
3)會話將相機采集到的二維碼圖像轉(zhuǎn)換成字符串數(shù)據(jù)

2.原生掃描中用到的幾個類

AVCaptureDevice                        // 拍攝設(shè)備
AVCaptureDeviceInput                   // 輸入設(shè)備
AVCaptureMetadataOutput                // 元數(shù)據(jù)輸出
AVCaptureSession                       // 拍攝會話
AVCaptureVideoPreviewLayer             // 視頻預覽圖層
代碼如下
- (void)readQRCode{

// 1.實例化拍攝裝備
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

// 2.設(shè)置輸入設(shè)備
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];

// 3.設(shè)置元數(shù)據(jù)輸出
AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];
[output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];   // 設(shè)置代理

// 4.添加拍攝會話
self.session = [[AVCaptureSession alloc] init];
[self.session addInput:input];       // 添加會話輸入
[self.session addOutput:output];     // 添加會話輸出

[output setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]];      // 設(shè)置輸出數(shù)據(jù)類型(需要將元數(shù)據(jù)輸出添加到會話后才能制定元數(shù)據(jù)類型,否則會報錯)

// 5.視頻預覽圖層
self.previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:_session]; // 傳遞session是為了告訴圖層將來顯示什么內(nèi)容
self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;   // 顯示方式
// 設(shè)置videoGravity,顧名思義就是視頻播放時的拉伸方式,默認是AVLayerVideoGravityResizeAspect
// AVLayerVideoGravityResizeAspect 保持視頻的寬高比并使播放內(nèi)容自動適應播放窗口的大小咳焚。
// AVLayerVideoGravityResizeAspectFill 和前者類似革半,但它是以播放內(nèi)容填充而不是適應播放窗口的大小。最后一個值會拉伸播放內(nèi)容以適應播放窗口.
// 因為考慮到全屏顯示以及設(shè)備自適應,這里我們采用fill填充

self.previewLayer.frame = self.view.bounds;
[self.view.layer insertSublayer:self.previewLayer atIndex:0]; // 將圖層插入當前圖層

// 6.啟動會話
[self.session startRunning];
}

AVCaptureMetadataOutputObjectsDelegate 的代理方法
/**
 掃描結(jié)果處理

 @param captureOutput 輸出數(shù)據(jù)源
 @param metadataObjects 掃描結(jié)果數(shù)組
 @param connection 用于協(xié)調(diào)輸入與輸出之間的數(shù)據(jù)流
 */
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{

// 1.判斷掃描結(jié)果的數(shù)據(jù)是否存在
if ([metadataObjects count] > 0) {
    // 2.如果存在數(shù)據(jù)延刘,則停止會話
    [self.session stopRunning];
    // 3.刪除預覽圖層
    [self.previewLayer removeFromSuperlayer];
    
    AVMetadataMachineReadableCodeObject *metadataObject = metadataObjects[0];
    
    // AVMetadataMachineReadableCodeObject 是AVMetadataObject的具體子類定義的特性檢測一維或二維條形碼六敬。
    // AVMetadataMachineReadableCodeObject代表一個單一的照片中發(fā)現(xiàn)機器可讀的代碼。這是一個不可變對象描述條碼的特性和載荷普泡。
    // 在支持的平臺上,AVCaptureMetadataOutput輸出檢測機器可讀的代碼對象的數(shù)組
    
    NSString *stringValue = metadataObject.stringValue;
    
    if ([stringValue containsString:@"http"]) {
        
        // 如果是字符串审编,則打開連接
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:stringValue] options:[NSDictionary dictionary] completionHandler:^(BOOL success) {
            
            if (success) {
                NSLog(@"成功");
            }
        }];
    }else{
        NSLog(@"普通字符串:%@",stringValue);     // 可以將字符串放到需要用到的地方(比如label)
     }
   }
 }

小結(jié)

代碼已經(jīng)上傳至git:
--> 傳送門:https://github.com/272095249/CreateAndReadQRCode.git

有問題歡迎指正以及相互探討 —— CoderSun

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末割笙,一起剝皮案震驚了整個濱河市眯亦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌妻率,老刑警劉巖宫静,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異伏伯,居然都是意外死亡捌袜,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進店門弄唧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人候引,你說我怎么就攤上這事」淇” “怎么了麸俘?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵疾掰,是天一觀的道長。 經(jīng)常有香客問我静檬,道長,這世上最難降的妖魔是什么侮腹? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任稻励,我火速辦了婚禮,結(jié)果婚禮上加矛,老公的妹妹穿的比我還像新娘煤篙。我一直安慰自己,他們只是感情好辑奈,可當我...
    茶點故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布鸠窗。 她就那樣靜靜地躺著,像睡著了一般稍计。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上涨颜,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天庭瑰,我揣著相機與錄音,去河邊找鬼弹灭。 笑死,一個胖子當著我的面吹牛逻翁,可吹牛的內(nèi)容都是我干的捡鱼。 我是一名探鬼主播,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼缠诅,長吁一口氣:“原來是場噩夢啊……” “哼乍迄!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起闯两,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤漾狼,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后邦投,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體擅笔,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡猛们,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了绿店。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,872評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡借嗽,死狀恐怖转培,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情惨寿,我是刑警寧澤,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布裂垦,位于F島的核電站肌索,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏企量。R本人自食惡果不足惜亡电,卻給世界環(huán)境...
    茶點故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望恕汇。 院中可真熱鬧或辖,春花似錦、人聲如沸颂暇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽县爬。三九已至,卻和暖如春察迟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背扎瓶。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工概荷, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人乍赫。 一個月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓雷厂,卻偏偏與公主長得像,于是被迫代替她去往敵國和親改鲫。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,876評論 2 361

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