iOS7からAVCaptureMetadataOutputでQRコードが取得できるので、とても簡単になりましたね。ここでは試していませんが、iOS8でカメラの露光調整も制御できるようになるみたいで、ますます実用度が上がっていきますね。
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する、など。
先に作成した 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.
}
}