Swift4如何掃描二維碼瞭解一下

搶手的哥發表於2018-04-20

1.掃碼簡史

這些年移動網際網路的普及,也讓二維碼技術成功的推廣。在遙遠的iOS7.0之前的年代,我們實現二維碼掃描的功能,還需要藉助兩大開源元件ZXing和ZBar來實現。iOS7.0以後,蘋果提供了AVFoundation框架,來實現二維碼是掃碼,而且效率更高。 與此同時,蘋果的Swift開發語言,也經歷了從1.0誕生到4.1,其中不乏一些新特性以及API的變化。

本文講解了如何用Swift4,實現二維碼掃描的功能

2.具體實現

2.1許可權控制

實現二維碼掃描,必然要開啟手機攝像頭,就需要獲取許可權。首先,在你的專案工程的info.plist中加入如下key-value,否則app除錯的時候崩潰。

<key>NSCameraUsageDescription</key>
<string>CameraUsageDescription</string>
複製程式碼

另外需要手動去檢測當前APP的攝像頭許可權。如下程式碼:

func checkCameraAuth() -> Bool {
let status = AVCaptureDevice.authorizationStatus(for: .video)
return status == .authorized
}
複製程式碼

不難看出,status是個列舉值,只有 .authorized才是已經獲取攝像頭許可權,其餘的都不行。

2.2 上程式碼

2.2.1 初始化

匯入AVFoundation框架之後,我們就可以初始化捕捉裝置、建立捕捉會話、輸入媒體型別、設定代理等

// 捕捉裝置
guard let device = AVCaptureDevice.default(for: .video)  else {
return
}
do {
// 輸入
inPut: AVCaptureDeviceInput = try AVCaptureDeviceInput.init(device: device)
} catch  {
print(error)
}

/// 輸出
let outPut: AVCaptureMetadataOutput = {
let outPut = AVCaptureMetadataOutput.init()
outPut.connection(with: .metadata)
return outPut
}()

/// 會話 session
let session: AVCaptureSession = {
let session = AVCaptureSession.init()
if session.canSetSessionPreset(.high){
session.sessionPreset = .high
}
return session
}()

/// 預覽層
let preLayer: AVCaptureVideoPreviewLayer = AVCaptureVideoPreviewLayer.init()
複製程式碼

2.2.2 設定代理

初始化之後,開始設定代理

// 設代理
outPut.setMetadataObjectsDelegate(self as AVCaptureMetadataOutputObjectsDelegate, queue: DispatchQueue.main)
// 指定預覽層的捕捉會話
preLayer.session = session
複製程式碼

2.2.3 指定會話輸入輸出

然後把捕捉會話新增輸入輸出

// 捕捉會話加入input和output
if session.canAddInput(input) && session.canAddOutput(outPut) {
session.addInput(input)
session.addOutput(outPut)
// 設定後設資料處理型別(注意, 一定要將設定後設資料處理型別的程式碼新增到  會話新增輸出之後)
outPut.metadataObjectTypes = [.ean13, .ean8, .upce, .code39, .code93, .code128, .code39Mod43, .qr]
}
複製程式碼

設定後設資料處理型別, 可見不僅有二維碼,而且還有其他條碼,就不一一介紹了。注意, 一定要將設定後設資料處理型別的程式碼新增到會話新增輸出之後。

2.2.4 新增會話預覽圖層

接著開始在頁面新增預覽層, 這樣才能看到攝像頭捕捉到的畫面。

// 新增預覽圖層
let flag = view.layer.sublayers?.contains(preLayer)
if flag == false || flag == nil {
self.preLayer.frame = view.bounds
view.layer.insertSublayer(preLayer, at: 0)
}
複製程式碼

2.2.5 開啟會話

到此為止,這個session捕捉會話需要的引數都全了,然後開始愉快的開始這個會話

// 啟動會話
session.startRunning()
複製程式碼

2.2.6 監聽捕捉會話輸出代理

開啟捕捉會話,我們就可以在代理方法中檢視會話捕捉到的東西。

func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!)
複製程式碼

識別到的就在這個方法裡告訴你。 什麼?什麼?,方法不呼叫? 敲黑板!!!API有變化了 Swift4.0的代理方法在下面

func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection){
var resultStrs = [String]()
for obj in metadataObjects {
guard let codeObj = obj as? AVMetadataMachineReadableCodeObject else {
return
} 
resultStrs.append(codeObj.stringValue ?? "")
}
}
複製程式碼

在這個方法裡面就能拿到掃碼之後的結果了。

2.2.7 思考

寫到這裡,不經停下思考: 1.這裡還只是基本的掃碼功能,就已經這麼多程式碼了,關於掃碼頁面的長啥樣子的程式碼我還沒寫; 2.一般開發中頁面少不了UI的網路的程式碼,難道我要再把這麼一大坨AVFoundation程式碼都寫到控制器嗎? 3.如果我一個專案裡面,不止一個地方用到掃碼,難道我還要再把這麼多程式碼再複製幾遍

WTF.png

3.封裝

高內聚 低耦合 就按照這個原則來封裝。 1.首先把這些AVFoundation模組的程式碼,統統抽到一個工具類裡,需要的時候,直接拿工具類呼叫,識別結果delegate返回。 2.可以根據經驗,把一些定製的需求也放進去,比如說掃碼的時候,中間透明的框框,加上週邊的黑色蒙板。 3.擴充套件一些其他功能,比如掃碼成功播放一段提示音等待

什麼?你準備動手了?彆著急,我已經弄好了,使勁戳??

HRQRCodeScanTool

最簡單的,在控制器中,你只需要

// in ViewController
HRQRCodeScanTool.shared.delegate  = self
HRQRCodeScanTool.shared.beginScanInView(view: view)
複製程式碼

然後掃碼結果代理返回

// scan result will call in  delegate methods 
func scanQRCodeFaild(error: HRQRCodeTooError){
print(error)
}

func scanQRCodeSuccess(resultStrs: [String]){
print(resultStrs.first)
}
複製程式碼

如果你需要二維碼描邊,你只需要設定這幾個屬性

open var isDrawQRCodeRect: Bool    true    是否描繪二維碼邊框 預設true
open var drawRectColor: UIColor    UIColor.red    二維碼邊框顏色 預設紅色
open var drawRectLineWith: CGFloat    2    二維碼邊框線寬 預設2
複製程式碼

如果你需要新增蒙板,你只需要設定這幾個屬性

open var isShowMask: Bool    true    是否展示黑色蒙版板層 預設開啟
open var maskColor: UIColor    Black.alpha 0.5    蒙板層 預設黑色 alpha 0.5
open var centerWidth: CGFloat    200    中心非蒙板區域的寬
open var centerHeight: CGFloat    5.0    中心非蒙板區域的寬
open var centerPosition: CGPoint?    nil    中心非蒙板區域的中心點 預設Veiw的中心
複製程式碼

哪裡需要掃碼,直接接入工具類,沒多少行程式碼搞定,就問你爽不爽。 另外,專案裡還提供了兩個擴充套件,用來識別二維碼圖片,以及圖片生成二維碼,需要的各位看官老爺自取。

yeah.png
還支援Cocoapods哦

相關文章