Pull to refresh

Сканируем и распознаем QR-коды из своего iOS-приложения

Reading time 7 min
Views 20K
QR-коды сегодня используются практически везде, где только можно себе представить. Вполне очевидно, что многим разработчикам было бы интересно узнать, как организовать сканирование и распознавание QR-кодов в своих приложениях для мобильных устройств.

В процессе разработки собственного приложения для iOS столкнулся с тем, что информации на русском языке по теме обработки QR-кодов на просторах Интернета крайне мало. Разобравшись с самим приложением, решил, что необходимо исправить эту вопиюще несправедливую ситуацию. Под катом Вы найдете описание процесса разработки крайне простого приложения, распознающего QR-коды, и представляющего интерес для начинающих iOS-разработчиков. Данная заметка предполагает наличие базовых знаний особенностей работы в Xcode и программирования под iOS.

Разработка будет вестись для Xcode 4.1, для более ранних версий Xcode (начиная с версии 3.2.3) процесс будет практически аналогичным.
Задача сканирования и распознавания образов, вообще говоря, является достаточно сложной с точки зрения математической и технической реализации. Иными словами, разработать «с нуля» приложение, распознающее штрих-код или QR-код, достаточно сложно. К счастью для нас прогресс не стоит на месте и большую часть сложной работы по сканированию и распознаванию уже кто-то когда-то решил. Чем мы и воспользуемся.
Итак, для работы Вам потребуется:
  • Mac OS X >= 10.6.x (Snow Leopard), у меня, соответственно, 10.7.2 Lion.
  • Xcode >= 3.2.3, я работал в версии 4.1.
  • iPhone >= 3GS, я тестировал на iPhone 3GS и iPad 2.
  • iOS 4.0 и выше на устройстве (на самом деле, можно и 3.1).
  • Учетная запись iOS-разработчика, т.к. без нее нельзя тестировать разработанные приложения на физических устройствах.

Поскольку эмулятор iOS устройств, распространяемый с Xcode, не умеет эмулировать камеру, для тестирования приложения нам потребуется реальное устройство – iPhone, iPod Touch или iPad 2, т.е. любое устройство с камерой, выпущенное в течение последних 2 лет вполне себе подойдет.

Также для работы мы будем использовать SDK для сканирования и распознавания QR-кодов, который возьмет на себе обработку графического изображения QR-кода и его преобразование в текстовую информацию. Существуют несколько готовых open-source библиотек, предлагающих подобный функционал, мы будем использовать SDK ZBar iPhone SDK версии 1.2 (подойдет и версия выше 1.2), скачать которую можно тут.

По указанной ссылке Вы скачаете образ ZBarSDK-1.2.dmg, внутри которого нас будет интересовать папка ZBarSDK, в которой и содержится нужная нам библиотека.

Итак, приступим.

1. Запустим Xcode, создадим в нем новый проект «View-based Application», назовем его QR Scanner, и сохраним его где-нибудь в удобном для Вас месте на диске.

2. В Project navigator откроем QR_ScannerViewController.xib.

3. Разместим на форме Round Rect Button и разместим на ней, например, текст «Сканировать QR-код».

4. Разместим в верхней части формы элемент Image View, установим в Инспекторе объектов свойство view mode в Aspect Fit.

5. Разместим в нижней части формы элемент Text View, уберем текст-заглушку, вместо него разместим, например, текст «Для начала сканирования QR-кода нажмите на кнопку в нижней части экрана». Снимем в Инспекторе объектов галочку User Interaction Enabled.

6. Добавим аутлеты в код контроллера, для этого откроем QR_ScannerViewController.h и приведем его к такому виду:
#import <UIKit/UIKit.h>
@interface QR_ScannerViewController : UIViewController {
    UITextView *resultText;
    UIImageView *resultImage;
}
@property (nonatomic, retain) IBOutlet UIImageView *resultImage;
@property (nonatomic, retain) IBOutlet UITextView *resultText;
- (IBAction)scanButtonTapped;
@end


Как видно из кода, мы объявили два аутлета на элементы управления UITextView и UIImageView, которые мы разместили на нашей форме. Кроме этого, мы объявили IBAction, который будет обрабатывать нажатие нашей кнопки и сканировать QR-код.

7. Откроем QR_ScannerViewController.xib и свяжем созданные нами аутлеты и действие scanButtonTapped с соответствующими элементами формы:
  • Аутлет resultImage свяжем с элементом ImageView.
  • Аутлет resultText свяжем с элементом TextView.
  • Действие scanButtonTapped свяжем с событием TouchUpInside кнопки Round Rect Button.

8. Теперь нам надо создать реализацию объявленных в заголовочном файле класса QR_ScannerViewController объектов. Откроем файл QR_ScannerViewController.m и приведем его к следующему виду:
#import "QR_ScannerViewController.h"
@implementation QR_ScannerViewController
@synthesize resultImage;
@synthesize resultText;
- (IBAction)scanButtonTapped{
    NSLog(@"Now we are scanning QR-code...");
}
- (void)didReceiveMemoryWarning
{    [super didReceiveMemoryWarning];}
- (void)viewDidUnload
{
    [super viewDidUnload];
    self.resultText = nil;
    self.resultImage = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation
{ return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);}
- (void) dealloc {
    [resultImage release];
    [resultText release];
    [super dealloc];
}

Если Вы не слишком хорошо знакомы с разработкой приложений в Xcode, не пугайтесь – большую часть кода среда разработки добавила в этой файл сама. Мы всего лишь реализовали объявленные в заголовочном файле объекты и действие:
@synthesize resultImage;
@synthesize resultText;
- (IBAction)scanButtonTapped{
    NSLog(@"Now we are scanning QR-code...");
}

Кроме того, мы добавили код для освобождения аутлетов при выгрузке формы из памяти (viewDidUnload):
self.resultText = nil;
self.resultImage = nil;

Также освобождаем память в dealloc:
[resultImage release];
[resultText release];


9. Теперь нам необходимо непосредственно включить в наше приложение скаченную ранее библиотеку ZBarSDK. Для этого откроем образ диска ZBarSDK-1.2.dmg, найдем в нем папку ZBarSDK и перетащим ее из Finder в свой проект в Xcode.

10. Далее нам необходимо добавить несколько дополнительных библиотек в наш проект. В свойствах Target нашего проекта откроем вкладку Build Phases, раскроем выпадающий список Link Binary With Libraries и нажимая на плюсик в нижней левой части этого списка добавим следующие библиотеки:
  • AVFoundation.framework
  • CoreMedia.framework
  • CoreVideo.framework
  • QuartzCore.framework
  • libiconv.dylib

11. Импортируем заголовочный файл нашего SDK. Для этого откроем файл «QR Scanner-Prefix.pch» и добавим в него строчку:
 #import "ZBarSDK.h" 


12. Для нашего класса контроллера QR_ScannerViewController объявим поддержку протокола делегата <ZBarReaderDelegate>, для этого в файле QR_ScannerViewController.h поправим объявление класса:
@interface QR_ScannerViewController : UIViewController <ZBarReaderDelegate>{
    UITextView *resultText;
    UIImageView *resultImage;
}


13. Теперь мы полностью готовы к тому, чтобы заставить приложение начать делать что-то полезное. В файле QR_ScannerViewController.m изменим код scanButtonTapped на следующий:
- (IBAction)scanButtonTapped{
    // Создаем объект, получающий картинку с камеры
    ZBarReaderViewController *reader = [ZBarReaderViewController new];
    reader.readerDelegate = self;
    reader.supportedOrientationsMask = ZBarOrientationMaskAll;
    ZBarImageScanner *scanner = reader.scanner;
/* 
Мы будем считывать только QR-коды. Для этого мы сперва отключим распознавание всех поддерживаемых библиотекой штрих-кодов…
*/
    [scanner setSymbology:0 config:ZBAR_CFG_ENABLE to:0];
/*
… а затем включим распознавание QR-кодов:
*/
    [scanner setSymbology:ZBAR_QRCODE config:ZBAR_CFG_ENABLE to:1];
    reader.readerView.zoom = 1.0;
/*
Далее показываем пользователю в модальном режиме представление (форму), сканирующую QR-код:
*/
    [self presentModalViewController:reader animated:YES];
    [reader release];
}

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

14. Однако считать и обработать QR-код мало, надо еще показать пользователю результаты обработки. Для этого нам необходимо реализовать следующий метод делегата (все в том же QR_ScannerViewController.m):
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
/*
В результате распознавания  в info в общем случае возвращается что-то «перечисляемое»:
*/
    id<NSFastEnumeration> results = [info objectForKey:ZBarReaderControllerResults];
/*
Опять же в общем случае результатов может быть несколько, следующий код всего лишь берет первый считанный и распознанный QR-код:
*/
ZBarSymbol *symbol = nil;
    for(symbol in results)
        // Считываем первый полученный результат
        break;
/*
Результат считывания и распознавания заносим в текстовое поле на форме через аутлет resultText:
*/ 
    resultText.text = symbol.data;
/*
Исходную картинку с QR-кодом заносим в объект UIImageView через аутлет resultImage:
*/
    resultImage.image =
    [info objectForKey: UIImagePickerControllerOriginalImage];
    
    // Прячем форму, с помощью которой фотографировали QR-код
    [picker dismissModalViewControllerAnimated:YES];
}

После работы этого метода с экрана будет убрано представление, фотографировавшее QR-код и показано исходное представление, разработанное нами в файле QR_ScannerViewController.xib. На этом представлении можно будет увидеть фото QR-кода и текст этого QR-кода.

15. Вот и все! Далее сохраняем проект, компилируем, запускаем на устройстве.

16. Для сканирования QR-кода необходимо нажать на кнопку «Сканировать QR-код» и навести камеру на изображение QR-кода. Программа автоматически «узнает» QR-код, сфотографирует его и распознает, после чего выведет содержащуюся в нем информацию на экран.

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

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

В заключение несколько полезных ссылок по теме данной заметки:
1. Сайт разработчиков библиотеки ZBarSDK.
2. Википедия о QR-кодах
Tags:
Hubs:
+18
Comments 6
Comments Comments 6

Articles