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

1.掃碼簡(jiǎn)史

這些年移動(dòng)互聯(lián)網(wǎng)的普及,也讓二維碼技術(shù)成功的推廣。在遙遠(yuǎn)的iOS7.0之前的年代,我們實(shí)現(xiàn)二維碼掃描的功能,還需要借助兩大開(kāi)源組件ZXing和ZBar來(lái)實(shí)現(xiàn)。iOS7.0以后,蘋(píng)果提供了AVFoundation框架,來(lái)實(shí)現(xiàn)二維碼是掃碼,而且效率更高。
與此同時(shí),蘋(píng)果的Swift開(kāi)發(fā)語(yǔ)言,也經(jīng)歷了從1.0誕生到4.1,其中不乏一些新特性以及API的變化。

本文講解了如何用Swift4,實(shí)現(xiàn)二維碼掃描的功能

2.具體實(shí)現(xiàn)

2.1權(quán)限控制

實(shí)現(xiàn)二維碼掃描,必然要打開(kāi)手機(jī)攝像頭,就需要獲取權(quán)限。首先,在你的項(xiàng)目工程的info.plist中加入如下key-value,否則app調(diào)試的時(shí)候崩潰。

<key>NSCameraUsageDescription</key>
<string>CameraUsageDescription</string>

另外需要手動(dòng)去檢測(cè)當(dāng)前APP的攝像頭權(quán)限。如下代碼:

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

不難看出,status是個(gè)枚舉值,只有 .authorized才是已經(jīng)獲取攝像頭權(quán)限,其余的都不行。

2.2 上代碼

2.2.1 初始化

導(dǎo)入AVFoundation框架之后,我們就可以初始化捕捉設(shè)備、創(chuàng)建捕捉會(huì)話、輸入媒體類(lèi)型、設(shè)置代理等

// 捕捉設(shè)備
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
    }()

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

/// 預(yù)覽層
let preLayer: AVCaptureVideoPreviewLayer = AVCaptureVideoPreviewLayer.init()

2.2.2 設(shè)置代理

初始化之后,開(kāi)始設(shè)置代理

// 設(shè)代理
outPut.setMetadataObjectsDelegate(self as AVCaptureMetadataOutputObjectsDelegate, queue: DispatchQueue.main)
// 指定預(yù)覽層的捕捉會(huì)話
preLayer.session = session

2.2.3 指定會(huì)話輸入輸出

然后把捕捉會(huì)話添加輸入輸出

// 捕捉會(huì)話加入input和output
  if session.canAddInput(input) && session.canAddOutput(outPut) {
            session.addInput(input)
            session.addOutput(outPut)
            // 設(shè)置元數(shù)據(jù)處理類(lèi)型(注意, 一定要將設(shè)置元數(shù)據(jù)處理類(lèi)型的代碼添加到  會(huì)話添加輸出之后)
            outPut.metadataObjectTypes = [.ean13, .ean8, .upce, .code39, .code93, .code128, .code39Mod43, .qr]
        }

設(shè)置元數(shù)據(jù)處理類(lèi)型, 可見(jiàn)不僅有二維碼,而且還有其他條碼,就不一一介紹了。注意, 一定要將設(shè)置元數(shù)據(jù)處理類(lèi)型的代碼添加到會(huì)話添加輸出之后。

2.2.4 添加會(huì)話預(yù)覽圖層

接著開(kāi)始在頁(yè)面添加預(yù)覽層, 這樣才能看到攝像頭捕捉到的畫(huà)面。

 // 添加預(yù)覽圖層
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 開(kāi)啟會(huì)話

到此為止,這個(gè)session捕捉會(huì)話需要的參數(shù)都全了,然后開(kāi)始愉快的開(kāi)始這個(gè)會(huì)話

// 啟動(dòng)會(huì)話
session.startRunning()

2.2.6 監(jiān)聽(tīng)捕捉會(huì)話輸出代理

開(kāi)啟捕捉會(huì)話,我們就可以在代理方法中查看會(huì)話捕捉到的東西。

func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!)

識(shí)別到的就在這個(gè)方法里告訴你。
什么?什么?,方法不調(diào)用?
敲黑板!?。PI有變化了
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 ?? "")
        }
}

在這個(gè)方法里面就能拿到掃碼之后的結(jié)果了。

2.2.7 思考

寫(xiě)到這里,不經(jīng)停下思考:
1.這里還只是基本的掃碼功能,就已經(jīng)這么多代碼了,關(guān)于掃碼頁(yè)面的長(zhǎng)啥樣子的代碼我還沒(méi)寫(xiě);
2.一般開(kāi)發(fā)中頁(yè)面少不了UI的網(wǎng)絡(luò)的代碼,難道我要再把這么一大坨AVFoundation代碼都寫(xiě)到控制器嗎?
3.如果我一個(gè)項(xiàng)目里面,不止一個(gè)地方用到掃碼,難道我還要再把這么多代碼再?gòu)?fù)制幾遍

WTF.png

3.封裝

高內(nèi)聚 低耦合
就按照這個(gè)原則來(lái)封裝。
1.首先把這些AVFoundation模塊的代碼,統(tǒng)統(tǒng)抽到一個(gè)工具類(lèi)里,需要的時(shí)候,直接拿工具類(lèi)調(diào)用,識(shí)別結(jié)果delegate返回。
2.可以根據(jù)經(jīng)驗(yàn),把一些定制的需求也放進(jìn)去,比如說(shuō)掃碼的時(shí)候,中間透明的框框,加上周邊的黑色蒙板。
3.擴(kuò)展一些其他功能,比如掃碼成功播放一段提示音等待

什么?你準(zhǔn)備動(dòng)手了?別著急,我已經(jīng)弄好了,使勁戳????

HRQRCodeScanTool

最簡(jiǎn)單的,在控制器中,你只需要

// in ViewController
HRQRCodeScanTool.shared.delegate  = self
HRQRCodeScanTool.shared.beginScanInView(view: view)

然后掃碼結(jié)果代理返回

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

func scanQRCodeSuccess(resultStrs: [String]){
  print(resultStrs.first)
}

如果你需要二維碼描邊,你只需要設(shè)置這幾個(gè)屬性

open var isDrawQRCodeRect: Bool true    是否描繪二維碼邊框 默認(rèn)true
open var drawRectColor: UIColor UIColor.red 二維碼邊框顏色 默認(rèn)紅色
open var drawRectLineWith: CGFloat  2   二維碼邊框線寬 默認(rèn)2

如果你需要添加蒙板,你只需要設(shè)置這幾個(gè)屬性

open var isShowMask: Bool   true    是否展示黑色蒙版板層 默認(rèn)開(kāi)啟
open var maskColor: UIColor Black.alpha 0.5 蒙板層 默認(rèn)黑色 alpha 0.5
open var centerWidth: CGFloat   200 中心非蒙板區(qū)域的寬
open var centerHeight: CGFloat  5.0 中心非蒙板區(qū)域的寬
open var centerPosition: CGPoint?   nil 中心非蒙板區(qū)域的中心點(diǎn) 默認(rèn)Veiw的中心

哪里需要掃碼,直接接入工具類(lèi),沒(méi)多少行代碼搞定,就問(wèn)你爽不爽。
另外,項(xiàng)目里還提供了兩個(gè)擴(kuò)展,用來(lái)識(shí)別二維碼圖片,以及圖片生成二維碼,需要的各位看官老爺自取。


yeah.png

還支持Cocoapods哦

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容