2014年6月29日日曜日

[iOS] Swift Language でQRコード認識

XCode6-Beta2 と iOS8-beta2 on iPhone5で試しに書いてみました。
iOS7からAVCaptureMetadataOutputでQRコードが取得できるので、とても簡単になりましたね。ここでは試していませんが、iOS8でカメラの露光調整も制御できるようになるみたいで、ますます実用度が上がっていきますね。


1. プロジェクトの作成

XCodeでFile > New > Project... で iOSのSingle View Applicationを選択した後、以下のように View の下に View と Table View を2つ置きます。
Table View Cellの Identifier に "Cell" を入力しておきます。また、Table View、Table View Cell のバックグラウンドカラーを Clear Color にしておきます。

※一応、わざわざ View の下に 2 つ View を置いているのは、一方にカメラのプレビューのレイヤを結びつけて、もう一方にQRコードスキャンした結果を表示させたいためです。もっといい方法あるかもしれません。例えば、CATextLayerで結果表示させるのだったら、Viewは1つにして、previewおよびCATextLayerを2つaddLayerする、など。


2. ViewController.swiftの記述

ViewController.swiftを記述していきます。
先に作成した View 以下の View と TableView をそれぞれ IBOutlet で _preview と _tableviewとしてつなげておきます。その上で以下を記述します。

import UIKit
import AVFoundation
import QuartzCore

class ViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate, UITableViewDataSource, UITableViewDelegate {
    
    @IBOutlet var _tableview: UITableView
    @IBOutlet var _preview: UIView
    var _session: AVCaptureSession!
    var _qrcodes : NSMutableArray = NSMutableArray()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        _session = AVCaptureSession()
        var devices : NSArray = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo)
        var device : AVCaptureDevice?
        for d : AnyObject in devices {
            if d.position == AVCaptureDevicePosition.Back {
                device = d as? AVCaptureDevice
                break
            }
        }
        // input
        var error : NSErrorPointer!
        var input : AVCaptureInput = AVCaptureDeviceInput.deviceInputWithDevice(device, error: error) as AVCaptureInput
        _session.addInput(input)

        // output
        var output : AVCaptureMetadataOutput = AVCaptureMetadataOutput()
        output.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
        _session.addOutput(output)
        
        // only QR
        output.metadataObjectTypes = [AVMetadataObjectTypeQRCode]
        
        // layer for preview
        var pvlayer : AVCaptureVideoPreviewLayer  = AVCaptureVideoPreviewLayer.layerWithSession(_session) as AVCaptureVideoPreviewLayer
        pvlayer.frame = self.view.bounds
        pvlayer.videoGravity = AVLayerVideoGravityResizeAspectFill
        _preview.layer.addSublayer(pvlayer)
        _session.startRunning()

    }
    
    func captureOutput(captureOutput:AVCaptureOutput?, didOutputMetadataObjects metadataObjects:NSArray, fromConnection connection:AVCaptureConnection?) {
        _qrcodes = NSMutableArray() // for new scanned qrcodes
        for metadata : AnyObject in metadataObjects {
            if (metadata as AVMetadataObject).type == AVMetadataObjectTypeQRCode {
                var qrcode : String = (metadata as AVMetadataMachineReadableCodeObject).stringValue
                println("\(qrcode)")
                _qrcodes.addObject(qrcode)
            }
        }
        _tableview.reloadData() // reload tableview
    }

    func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int  {
        return _qrcodes.count
    }

    func tableView(tableView: UITableView?, cellForRowAtIndexPath indexPath:NSIndexPath!) -> UITableViewCell! {
        let cell: UITableViewCell = _tableview.dequeueReusableCellWithIdentifier("Cell") as UITableViewCell // get custom cell
        cell.text = _qrcodes[indexPath.row] as String
        return cell
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

3. 実行

シミュレータではなく、実機で試してみます。QRコードをスキャンすると、オーバーレイで結果が表示されることを確認します。




以上です。

簡単ですね。Swift は .h を書かなくて良いので手間が省けますね。

0 件のコメント:

コメントを投稿