如同之前所提,我們依靠AVFoundation 框架來實作 QR Code 掃描功能。首先,打開ViewController.swift 檔案來導入此框架。
接著,我們需要實作AVCaptureMetadataOutputObjectsDelegate
協定。我們待會會討論到。現在更新以下這行程式:
|
class ViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate
|
繼續往下之前,在ViewController
類別宣告下面的變數。我們稍後會一個接一個說明。
|
var captureSession:AVCaptureSession?
var videoPreviewLayer:AVCaptureVideoPreviewLayer?
var qrCodeFrameView:UIView?
|
在viewdidload中放入
// 取得 AVCaptureDevice 類別的實體來初始化一個device物件,並提供video // 作為媒體型態參數
let captureDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
// 使用前面的 device 物件取得 AVCaptureDeviceInput 類別的實體
var error:NSError?
let input: AnyObject! = AVCaptureDeviceInput.deviceInputWithDevice(captureDevice, error: &error)
if (error != nil) {
// 假如有錯誤產生、 單純記錄其狀況,不再繼續。
println("\(error?.localizedDescription)")
return
}
// 初始化 captureSession 物件
captureSession = AVCaptureSession()
// 在capture session 設定輸入裝置
captureSession?.addInput(input as! AVCaptureInput)
// 初始化 AVCaptureMetadataOutput 物件並將其設定作為擷取session的輸出裝置
let captureMetadataOutput = AVCaptureMetadataOutput()
captureSession?.addOutput(captureMetadataOutput)
// 設定代理並使用預設的調度佇列來執行回呼(call back)
captureMetadataOutput.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
captureMetadataOutput.metadataObjectTypes = [AVMetadataObjectTypeQRCode]
// 初始化影像預覽層,並將其加為 viewPreview 視圖層的子層
videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
videoPreviewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
videoPreviewLayer?.frame = view.layer.bounds
view.layer.addSublayer(videoPreviewLayer)
// 開始影像擷取
captureSession?.startRunning()
view.bringSubviewToFront(messageLabel)
view.bringSubviewToFront(UpBlack)
view.bringSubviewToFront(Black)
view.bringSubviewToFront(CameraButton)
view.bringSubviewToFront(IconLogo)
// 初始化 QR Code Frame 來突顯 QR code
qrCodeFrameView = UIView()
qrCodeFrameView?.layer.borderColor = UIColor.redColor().CGColor
qrCodeFrameView?.layer.borderWidth = 2
view.addSubview(qrCodeFrameView!)
view.bringSubviewToFront(qrCodeFrameView!)
}
//這個 UIView
在畫面上是看不見的,因為qrCodeFrameView
物件的大小預設是零。接著,倘若QR Code被偵測到,我們將改變他的大小並將其轉成綠色方框。
func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {
// 檢查 metadataObjects 陣列是否為非空值,它至少需包含一個物件
if metadataObjects == nil || metadataObjects.count == 0 {
qrCodeFrameView?.frame = CGRectZero
qrCodeFrameView?.layer.borderColor = UIColor.greenColor().CGColor
messageLabel.text = "No QR code is detected"
return
}
// 取得元資料(metadata)物件
let metadataObj = metadataObjects[0] as! AVMetadataMachineReadableCodeObject
if metadataObj.type == AVMetadataObjectTypeQRCode {
//倘若發現的原資料與 QR code 原資料相同,便更新狀態標籤的文字並設定邊界
let barCodeObject = videoPreviewLayer?.transformedMetadataObjectForMetadataObject(metadataObj as
AVMetadataMachineReadableCodeObject) as! AVMetadataMachineReadableCodeObject
qrCodeFrameView?.frame = barCodeObject.bounds;
if metadataObj.stringValue != nil {
messageLabel.text = metadataObj.stringValue;
//這邊還可放入function,例如放入app(),即可換頁(參考"換頁並傳遞變數文章segue")
}
}
}