Разработка поиска по штрих-коду в мобильном приложении
Поиск по штрих-коду — это не просто «отсканировал и нашёл». Это пайплайн: захват изображения → распознавание → запрос к бэкенду или локальной базе → отображение результата. Каждый шаг может быть узким местом, и чаще всего проблемы возникают не в сканировании, а в том, что происходит после.
Платформенные возможности для распознавания
iOS: AVFoundation с AVMetadataObjectTypeEAN13Code, UPCA, QRCode и ещё десятком типов. Либо VisionKit — VNDetectBarcodesRequest с VNBarcodeObservation, который удобнее для обработки статичных изображений из галереи. DataScannerViewController (iOS 16+) — самый простой путь: один класс, встроенный UI, поддержка всех типов из коробки.
Android: ML Kit Barcode Scanning (com.google.mlkit:barcode-scanning) — работает офлайн, поддерживает 1D и 2D коды. Либо ZXing — проверенная библиотека, но значительно медленнее ML Kit на слабых устройствах.
Выбор зависит от минимальной версии OS и требований к офлайн-работе. ML Kit на Android требует Google Play Services; на устройствах без GMS (Huawei) нужен автономный bundled model.
Что действительно сложно: поиск, а не сканирование
Само сканирование — несколько строк кода. Сложность в архитектуре поиска:
Дедупликация результатов. Камера распознаёт один и тот же штрих-код десятки раз в секунду. Без дебаунса запрос уйдёт на сервер 50 раз до того, как пользователь уберёт камеру от полки. Решение: throttle на последний распознанный код с задержкой 800ms-1s.
Офлайн-поиск. Если каталог товаров доступен локально, поиск по SQLite или Room (Android) / CoreData (iOS) по полю barcode с индексом работает мгновенно. Без индекса на таблице из 100k товаров — 300-500ms даже на флагмане.
Неизвестный код. Что показывать, если штрих-код не найден в базе? Fallback на Open Food Facts API, GS1 lookup, или просто сообщение? Это продуктовое решение, но его нужно заложить в архитектуру заранее — иначе переделывать flow.
Пример: поиск с дебаунсом на iOS
private var lastScannedCode: String?
private var searchTimer: Timer?
func handleScannedCode(_ code: String) {
guard code != lastScannedCode else { return }
lastScannedCode = code
searchTimer?.invalidate()
searchTimer = Timer.scheduledTimer(withTimeInterval: 0.8, repeats: false) { [weak self] _ in
self?.performSearch(barcode: code)
}
}
Типы штрих-кодов и их обработка
| Тип | Применение | Примечание |
|---|---|---|
| EAN-13 / UPC-A | Розничные товары | Стандарт GS1 |
| Code 128 | Логистика, склад | Произвольный текст |
| QR Code | Ссылки, платежи | До 4096 байт |
| Data Matrix | Медикаменты | Маленький размер |
| ITF-14 | Групповая упаковка | Только цифры |
Если в техзадании не указаны конкретные типы — уточняем заранее. Включать поддержку всех типов без необходимости замедляет распознавание.
Срок разработки: 1-3 дня. Стоимость рассчитывается индивидуально после уточнения типов кодов и архитектуры поиска.







