Минимальный пример интеграции в iOS-приложение.
Состав SDK:
doc— документацияSamples/Swift/SESmartIDSample.xcodeproj— файл запуска семпла- `SESmartIDCore/*.xсframework — универсальная статическая библиотека для iOS-устройств и Simulator-ов.
SESmartIDCore/wrap— обертка для С++ библиотекиSESmartIDCore/include— C++ заголовочные файлы для взаимодействия Objc c интерфейсом библиотекиSESmartIDCore/data/*.se— конфигурационный файлSESmartID— Objective-C GUI-файлы приложения для взаимодействия с библиотекой
Описание интеграции
C++ библиотека поставляется в виде xcframework, содержащего бинарные файлы для различных архитектур iOS.
Поскольку Swift не может работать с C++ напрямую, интеграция библиотеки осуществляется через Objective-C обёртку, исходный код которой находится в директории wrap.
При сборке проекта в Xcode необходимо указать пути к заголовкам обёртки (wrap) и заголовкам интерфейса библиотеки (include) через Header Search Paths.
В директории SESmartID располагаются вспомогательные Objective-C файлы, упрощающие взаимодействие с библиотекой из Swift.
Swift-код получает доступ к публичным интерфейсам Objective-C кода через SmartID-Bridging-Header.h, который так же необходимо подключить в проекте.
Интеграция
Для добавления нашего SDK в ваш проект требуется сделать следующие действия:
- Перенести директорию
SESmartIDс исходными файлами из SDK в проект, при добавлении выбрать Create Groups. - Аналогично добавить директорию
SESmartIDCore/wrapс обёрткой и при добавлении выбрать Create Groups. - Добавить фреймворк
SESmartIDCore/lib/*.xcframeworkв свой проект на вкладке General -> Frameworks, Libraries, and Embedded Content -> «+», со свойством Do not embed. - Перенести директорию
SESmartIDCore/data, при добавлении выбрать Create Folder References. - В Header Search Paths указать следующие пути к заголовочным файлам проекта:
SESmartIDCore/includeSESmartIDCore/wrap/objcsecommon/includeSESmartIDCore/wrap/objcsecommon/include_implSESmartIDCore/wrap/objcidengine/includeSESmartIDCore/wrap/objcidengine/include_impl
- Если вы используете Swift, то добавьте
SESmartID/SmartID-Bridging-Header.hв Objective-C Bridging Header в настройках проекта
Итоговая структура проекта может выглядеть так:
├── data
├── wrap
└── SESmartID
├── Core
├── Controller
├── Media
└── SmartID-Bridging-Header.h
Работа с библиотекой
Взаимодействие с библиотекой происходит по следующему сценарию:
- Инициализация библиотеки с загрузкой конфигурационного файла.
- Создание настроек сессии, определяющих, что именно нужно распознавать.
- Подготовка изображения для передачи на распознавание (либо в цикле при обработке видео-потока, либо один раз при распознавании изображения из галереи)
- Инициализация сессии и передача в неё изображения.
- Разбор результата распознавания.
В модуле SESmartID вся логика работы с библиотекой полностью инкапсулирована, мы предлагаем использовать готовые делегаты и классы для удобной работы.
После добавления файла в проект файла *-Bridging-Header.h становятся доступны основные классы модуля: SmartIDViewController и SmartIDEngineInstance.
Чтобы получать результаты распознавания нужно также добавить в ваш класс протокол SmartIDViewControllerDelegate и сам объект обертки следующим образом:
// Инициализируем контроллер
let smartIDController: SmartIDViewController = {
let smartIDController = SmartIDViewController()
return smartIDController
}()
Затем необходимо сконфигурировать ядро:
override func viewDidLoad() {
super.viewDidLoad()
// Проставляем делегат, через который к нам придет результат распознавания
smartIDController.smartIDDelegate = self
...
// Инициализируем движок из бандла
DispatchQueue.main.async {
let bundlePaths = Bundle.main.paths(forResourcesOfType: "se", inDirectory: "data")
if bundlePaths.count == 1 {
self.engineInstance.initializeEngine(bundlePaths[0])
}
}
...
// Ассоциируем движок с контроллером
self.smartIDController.attach(self.engineInstance)
}
Когда потребуется отсканировать документ, нужно показать экран распознавания, указав, какие документы требуется распознавать в рамках текущей сессии:
- (void) showSmartIdViewController {
// Указываем, какие документы мы хотим распознавать
// Документация содержит подробное описание возможных типов документов и т.п.
smartIDController.sessionSettings().addEnabledDocumentTypes(withMask: "rus.passport.*")
// Можно контролировать таймаут в секундах, после которого распознавание закончится
smartIDController.sessionSettings().setOptionWithName("common.sessionTimeout", to: "5.0")
// Показываем экран распознавания
present(smartIDController, animated: true, completion: {
print("sample: smartIDViewController presented")
})
}
Во время сканирования будут вызываться методы, которые необходимо реализовать для получения результата распознавания:
func smartIDViewControllerDidRecognize(_ result: SEIdResult, from buffer: CMSampleBuffer?) {
let resultRef = result.getRef()
// Флаг "терминальности" проставляется, когда движок полностью уверен в результате или когда истек таймаут
if resultRef.getIsTerminal() {
// Здесь можно просмотреть результат распознавания, например, текстовые поля...
let textFieldsIter = result.textFieldsBegin()
let textFieldsEnd = result.textFieldsEnd()
while !textFieldsIter.isEqual(toIter: textFieldsEnd) {
print(textFieldsIter.getKey(), textFieldsIter.getValue().getValue().getFirstString())
textFieldsIter.advance()
}
// ...изображения
let imageFieldsIter = result.imageFieldsBegin()
let imageFieldsEnd = result.imageFieldsEnd()
while !imageFieldsIter.isEqual(toIter: imageFieldsEnd) {
print(imageFieldsIter.getKey())
let image = imageFieldsIter.getValue().getValue().convertToUIImage()
// image теперь можно вывести на экран
imageFieldsIter.advance()
}
// Закрываем экран распознавания
dismiss(animated: true, completion: nil)
}
}
// Вызывается при отмене сканирования пользователем
func smartIDviewControllerDidCancel() {
// Закрываем экран распознавания
dismiss(animated: true, completion: nil)
}
// Вызывается при остановке распознавания
func smartIDviewControllerDidStop(_ result: SEIdResult) {
// Здесь также можно просмотреть результат распознавания
// Закрываем экран распознавания
dismiss(animated: true, completion: nil)
}
Освобождение памяти
Рантайм iOS не управляет памятью C++. ARC/GC (в Objective-C/Swift) не имеет доступа к объектам, которые порождает С++. Большинство классов нашей библиотеки содержат фабричные методы, возвращающие указатели на объекты, выделенные в куче (new, new[], malloc, factory возвращает указатель), поэтому ответственность за освобождение памяти лежит на том, кто пользуется этим объектом!
Модуль SmartID инкапсулирует логику освобождения памяти при распознавании, но при использовании API библиотеки самостоятельно, ответственность за освобождение памяти вы берете на себя.
Обработка исключений
Наша библиотека может выдавать исключения подклассов se::common::BaseException при неверном вводе данных, некорректных вызовах и других ошибках. Модуль SmartID инкапсулирует логику отлова ошибок, но при использовании API библиотеки самостоятельно не забывайте об обработке исключений.
Модульная интеграция
Интеграция нашей библиотеки в iOS также возможна через SPM (Swift Package Manager) или CocoaPods.