Pull to refresh

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 этого примера.

Удачи!
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.