Статьи

Создание считывателя штрих-кода и метаданных в iOS

Более чем когда-либо пользователи ожидают, что приложения для iOS будут подключены. Данные проходят через приложения iOS в стремительном темпе. Он может прийти через API, через обмен сообщениями или связь с серверами. Сканирование многих типов доступных штрих-кодов является еще одной формой данных приложений, которые могут извлечь выгоду.

Начиная с iOS 7, Cocoa Touch поддерживает непосредственное чтение данных из штрих-кодов и других типов метаданных. В этом уроке я покажу, как настроить сканирование штрих-кода в приложениях iOS с помощью доступных встроенных сред.

Давайте кратко рассмотрим приложение, которое мы будем создавать. Загрузите стартовый проект с github здесь . Я намеренно сохранил минимальный пользовательский интерфейс и архитектуру, чтобы мы могли сосредоточиться на том, как кодировать сканирование штрих-кода.

После завершения приложение автоматически покажет прямую трансляцию задней камеры iPhone. Он будет активно искать метаданные штрих-кода. Когда он найдет его, он отобразит информацию о нем на ярлыках вверху и внизу прямой трансляции:

UIPreview

Давайте поговорим о задействованных рамках.

AVFoundation

AVFoundation — это зрелая структура, которая уже некоторое время является частью Cocoa Touch. Хотя это может быть пугающим для реализации из-за его широкого использования, настройка его для захвата метаданных очень проста.

Вот некоторые из ключевых объектов, которые используются для реализации сканирования штрих-кода:

AVCaptureSession

Координирует поток данных с аудио или видео устройств ввода и может транслировать их на выходы. Короче говоря, это движет весь процесс.

AVCaptureDevice

Этот класс представляет физическое устройство для захвата ввода для обратной связи с инициализированным экземпляром AVCaptureSession . В этом уроке этот класс будет представлять камеру на задней панели iPhone.

AVCaptureVideoPreviewLayer

Подкласс CALayer который отображает видео по мере его захвата устройством ввода. В этом уроке это экземпляр AVCaptureDevice .

AVCaptureMetaDataOutput

Перехватывает объекты метаданных из соединения захвата и передает их делегату для обработки. Этот класс также может указывать типы метаданных для захвата. Он предназначен для добавления в качестве вывода для AVCaptureSession .

Типы метаданных, которые он может перехватывать, следующие:

  • UPC-A
  • UPC-E
  • Код 39
  • Код 39 мод 43
  • Код 93
  • Код 128
  • EAN-8
  • EAN-13
  • ацтекский
  • PDF417
  • QR
  • Лицо

Теперь вовлеченные объекты понятны, давайте посмотрим на процесс на высоком уровне. Рабочий процесс для захвата штрих-кодов или любых метаданных с использованием AVFoundation выглядит следующим образом:

диаграмма

Отлично, теперь давайте перейдем к коду!

Настройка сеанса

Откройте ViewController.swift и взгляните на шаблон кода, который я включил. Я добавил несколько свойств, IBOutlets , и заглушил функции для начала работы. Если разработчик собирает и запускает сейчас, он ничего не сделает. Давайте изменим это.

Первый шаг — убедиться, что сессия создана. Это так же просто, как инициализация свойства, которое я сделал:

 let captureSession = AVCaptureSession() 

Позже мы вызовем startRunning() чтобы фактически начать ввод-вывод из captureSession и его ввода.

Подготовка устройства ввода

Внутри viewDidAppear: добавьте вызов в setupCaptureSession функцию setupCaptureSession .

viewDidAppear: тело метода должно выглядеть так:

 override func viewDidAppear(animated: Bool) { super.viewDidAppear(animated) self.setupCaptureSession() } 

Теперь добавьте код для этой функции:

 private func setupCaptureSession() { self.captureDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo) var setupError:NSError? if let deviceInput = AVCaptureDeviceInput.deviceInputWithDevice(self.captureDevice, error: &setupError) as? AVCaptureDeviceInput { //Add the input feed to the session and start it self.captureSession.addInput(deviceInput) self.setupPreviewLayer({ self.captureSession.startRunning() self.addMetaDataCaptureOutToSession() }) } else { self.showError(setupError!.localizedDescription) } } 

Сначала настройте устройство захвата, а затем проверьте, подходит ли оно для ввода данных. Если это невозможно, он инициализирует указатель на переменную ошибки и отображает ее пользователю. Обратите внимание, что если попытаться выполнить это на симуляторе, эта проверка завершится неудачно, поскольку у симулятора, очевидно, нет средств для создания какого-либо ввода.

Если устройство может производить ввод, добавьте его в сеанс и начните настройку свойства captureLayer для отображения прямой трансляции камеры.

Отображение ввода

Чтобы настроить уровень ввода, вызовите функцию setupPreviewLayer . Добавьте следующий код к этой функции сейчас:

 private func setupPreviewLayer(completion:() -> ()) { self.captureLayer = AVCaptureVideoPreviewLayer.layerWithSession(self.captureSession) as? AVCaptureVideoPreviewLayer if let capLayer = self.captureLayer { capLayer.videoGravity = AVLayerVideoGravityResizeAspectFill capLayer.frame = self.cameraView.frame self.view.layer.addSublayer(capLayer) completion() } else { self.showError("An error occured beginning video capture."") } } 

На этом этапе бессмысленно показывать предварительный просмотр источника входного сигнала (камера, расположенная сзади, в этом уроке). В этой части процесса программисту особо нечего делать, кроме добавления слоя, установки его кадра и выбора подходящего соотношения сторон.

Предполагая, что это было успешно, будет выполнено закрытие завершения. Это было добавлено в предыдущем фрагменте кода внутри setupCaptureSession . Закрытие будет делать две вещи: идентифицировать данные для захвата и установить контроллер представления в качестве делегата для обработки этих данных.

Указание вывода

До этого момента сеанс начался, было выбрано устройство для захвата ввода, добавлен ввод в сеанс, а затем отображен живой ввод для пользователя. AVFoundation сказать AVFoundation что захватывать, и настроить делегата.

Перейдите к функции addMetaDataCaptureOutToSession и добавьте этот код:

 private func addMetaDataCaptureOutToSession() { let metadata = AVCaptureMetadataOutput() self.captureSession.addOutput(metadata) metadata.metadataObjectTypes = metadata.availableMetadataObjectTypes metadata.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue()) } 

Эта функция начинается с создания экземпляра AVCaptureMetadataOutput а затем добавляет его в сеанс. Оттуда его свойство metadataObjectTypes устанавливается со всеми вещами, которые будут захвачены. Порядок здесь важен, потому что, если типы метаданных ищутся перед добавлением в сеанс, они не будут доступны.

Обратите внимание, что хотя это будет проверено с помощью сканирования штрих-кодов, оно будет искать все типы метаданных. Для большей степени специфичности просто передайте искомые типы metadataObjectTypes свойство metadataObjectTypes .

Наконец, установите этот контроллер представления в качестве делегата для обработки метаданных. Также необходимо указать, какой поток вызывается в AVFoundation поскольку AVFoundation для поддержки многопоточных операций.

AVCaptureMetadataOutputObjectsDelegate

Хотя этот контроллер представления определен как делегат захвата, все еще необходимо соответствовать протоколу. Сделайте это сейчас в верхней части файла контроллера представления, добавив AVCaptureMetadataOutputObjectsDelegate в конце строки создания:

 class ViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate 

Последнее, что нужно сделать, это обработать данные из метода делегата. Добавьте этот код в любое место в контроллере представления:

 func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) { for metaData in metadataObjects { let decodedData:AVMetadataMachineReadableCodeObject = metaData as! AVMetadataMachineReadableCodeObject self.lblDataInfo.text = decodedData.stringValue self.lblDataType.text = decodedData.type } } 

Этот код работает путем поиска захваченных объектов метаданных и их анализа. Поскольку он использует цикл for и не ищет метаданные определенного типа, он просто покажет последний захваченный элемент в пользовательском интерфейсе.

Теперь создайте и запустите приложение и укажите его на этот штрих-код:

Samplebarcode

Он должен распознавать штрих-код и отображать тип метаданных в верхней части пользовательского интерфейса, а анализируемую информацию — в нижней части.

Завершение

Надеюсь, этот урок продемонстрировал, что работа с AVFoundation не так плоха, как вы могли бы поверить в его репутацию. Начало работы с метаданными парсинга было выполнено с помощью всего нескольких функций и одного протокола. Если это было слишком сложно, не беспокойтесь, готовый проект можно скачать здесь.

Существует огромное количество данных, которые проявляются как один из типов метаданных, обсуждаемых здесь. Теперь вы можете использовать их в своем приложении!