2016年5月4日 星期三

[功能] 製作qrcode

如同之前所提,我們依靠AVFoundation 框架來實作 QR Code 掃描功能。首先,打開ViewController.swift 檔案來導入此框架。
1
import AVFoundation
接著,我們需要實作AVCaptureMetadataOutputObjectsDelegate 協定。我們待會會討論到。現在更新以下這行程式:
1
class ViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate

繼續往下之前,在ViewController 類別宣告下面的變數。我們稍後會一個接一個說明。
1
2
3
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")
            }
        }
    }



沒有留言:

張貼留言