Как стать автором
Обновить

XZing, ZBar. Зачем, когда есть нативные средства?

Привет!

Хочу поделиться с сообществом информацией о простом, и, главное внедренном в операционную систему (7.0+) возможностью распознания шрих-кодов, QR-кодов, и даже Aztec-кодов.
Как мне показалось, далеко не все в курсе этой возможности, и, надеюсь, эта информация будет для вас полезной.

Пример реализован на Swift.

1. Создадим проект



2. Добавим в storyboard, на наш единственный view controller вьюшку — обычный UIView



3. Слинкуем наш UIView с @IBOutlet cameraView в ViewController.swift
4. Бросим туда же UILabel (слинкуем с resultLabel)
5. Добавим UIButton (слинкуем с startStopButton)
6. Добавим «действие» (action) кнопки — startStopButtonTouchUpInside
7. Для полноты счастья я добавил звучок в приложение, и его проигрываение при успешном считывании
8. Не забудем добавить AVFoundation в список Frameworks
9. Отключим переориентацию устройства, сейчас пока не об этом:



Ниже приведен текст ViewController.swift:
import UIKit
import AVFoundation

class ViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate {
    
    @IBOutlet weak var startStopButton: UIButton!
    @IBOutlet weak var cameraView: UIView!
    @IBOutlet weak var resultLabel: UILabel!
   
    var captureSession: AVCaptureSession? // наша сессия для захвата видео с камеры
    var videoPreviewLayer: AVCaptureVideoPreviewLayer? // слой для отображения видео с камеры
    var audioPlayer: AVAudioPlayer? // будем щелкать звуком "затвора" при обнаружении кода
    var isActive: Bool = false // признак того, что мы сейчас в режиме поиска кода
    
    // старт-стоп распознования
    @IBAction func startStopButtonTouchUpInside(sender: AnyObject) {
        if isActive {
            stopRec()
        } else {
            startRec()
        }
    }

    // это можно сделать и в другом месте, но я решил тут
    override func viewDidLoad() {

        super.viewDidLoad()

        // пытаемся загрузить файл со звуком
        let path = NSBundle.mainBundle().pathForResource("chpok", ofType: "mp3")
        if path == nil {
            println("Файл со звуком не найден")
            return
        }
        
        let url = NSURL(string: path!)
        
        var error: NSError?
        
        audioPlayer = AVAudioPlayer(contentsOfURL: url, error: &error)
        if error != nil || audioPlayer == nil {
            println("что-то со звуком не так")
            if error != nil {
                println(error!.description);
            }
            return
        }
        
        // ура!
        audioPlayer!.prepareToPlay()
        
    }
    
    func startRec() -> Bool {

        if isActive {
            return true
        }
        
        var error: NSError?
        let captureDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
        let input = AVCaptureDeviceInput.deviceInputWithDevice(captureDevice, error: &error) as? AVCaptureDeviceInput
        
        if input == nil {
            // по каким-то причинам мы не имеем доступ к камере, выходим
            if error != nil {
                println(error!.description)
            }
            return false
        }
        
        // меняем текст кнопки
        startStopButton.setTitle("Закончить", forState: .Normal)
        
        // настраиваем перехват и анализ видеопотока
        
        // перехват
        captureSession = AVCaptureSession()
        captureSession!.addInput(input)
        let dispatchQueue = dispatch_queue_create("barCodeQueue", nil)
        
        let captureMetadataOutput = AVCaptureMetadataOutput()
        captureSession!.addOutput(captureMetadataOutput)
        
        captureMetadataOutput.setMetadataObjectsDelegate(self, queue:dispatchQueue)
        
        // тут я перечислил все виды бар-куар-кодов, которые поддерживаются на текущий момент
        captureMetadataOutput.metadataObjectTypes = [
            AVMetadataObjectTypeQRCode,
            AVMetadataObjectTypeUPCECode,
            AVMetadataObjectTypeCode39Code,
            AVMetadataObjectTypeCode39Mod43Code,
            AVMetadataObjectTypeEAN13Code,
            AVMetadataObjectTypeEAN8Code,
            AVMetadataObjectTypeCode93Code,
            AVMetadataObjectTypeCode128Code,
            AVMetadataObjectTypePDF417Code,
            AVMetadataObjectTypeAztecCode
        ]
        
        // ну и добавляем стрим с камеры, чтобы пользователь видел что он снимает
        videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        videoPreviewLayer!.videoGravity = AVLayerVideoGravityResizeAspectFill
        videoPreviewLayer!.frame = cameraView.layer.bounds
       
        cameraView.layer.addSublayer(videoPreviewLayer)
        
        // show must go on!
        captureSession!.startRunning()
        
        // ок, мы готовы
        isActive = true
        
        return true
    }
    
    func stopRec() -> Bool {

        // ну тут все очень просто:   
        if !isActive {
            return true
        }
        
        // меняем текст кнопки
        startStopButton.setTitle("Начать", forState: .Normal)
        
        // прекращаем съемку
        captureSession!.stopRunning()
        captureSession = nil;
        
        // убираем стрим с камеры
        videoPreviewLayer!.removeFromSuperlayer()
        
        // меняем текст
        resultLabel.text = "Наведите камеру"
        
        // ок, мы завершили
        isActive = false
        
        return true
    }
    
    func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {
        if metadataObjects != nil && metadataObjects.count > 0 {
            let metadataObj = metadataObjects[0] as AVMetadataMachineReadableCodeObject
            
            // меняем текст надписи в основном потоке
            dispatch_async(dispatch_get_main_queue()) {
                self.resultLabel.text = metadataObj.stringValue
            }
            
            audioPlayer?.play()
        }
        
        
    }
    
    
}


Надеюсь эта информация вам помогла (или поможет в будующем).

Ссылка на GitHub этого примера.

Удачи!
Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.