Более чем когда-либо пользователи ожидают, что приложения для iOS будут подключены. Данные проходят через приложения iOS в стремительном темпе. Он может прийти через API, через обмен сообщениями или связь с серверами. Сканирование многих типов доступных штрих-кодов является еще одной формой данных приложений, которые могут извлечь выгоду.
Начиная с iOS 7, Cocoa Touch поддерживает непосредственное чтение данных из штрих-кодов и других типов метаданных. В этом уроке я покажу, как настроить сканирование штрих-кода в приложениях iOS с помощью доступных встроенных сред.
Давайте кратко рассмотрим приложение, которое мы будем создавать. Загрузите стартовый проект с github здесь . Я намеренно сохранил минимальный пользовательский интерфейс и архитектуру, чтобы мы могли сосредоточиться на том, как кодировать сканирование штрих-кода.
После завершения приложение автоматически покажет прямую трансляцию задней камеры iPhone. Он будет активно искать метаданные штрих-кода. Когда он найдет его, он отобразит информацию о нем на ярлыках вверху и внизу прямой трансляции:
Давайте поговорим о задействованных рамках.
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 и не ищет метаданные определенного типа, он просто покажет последний захваченный элемент в пользовательском интерфейсе.
Теперь создайте и запустите приложение и укажите его на этот штрих-код:
Он должен распознавать штрих-код и отображать тип метаданных в верхней части пользовательского интерфейса, а анализируемую информацию — в нижней части.
Завершение
Надеюсь, этот урок продемонстрировал, что работа с AVFoundation
не так плоха, как вы могли бы поверить в его репутацию. Начало работы с метаданными парсинга было выполнено с помощью всего нескольких функций и одного протокола. Если это было слишком сложно, не беспокойтесь, готовый проект можно скачать здесь.
Существует огромное количество данных, которые проявляются как один из типов метаданных, обсуждаемых здесь. Теперь вы можете использовать их в своем приложении!