Bom pessoal vamos fazer mais um tutorial de objective C hoje vamos criar um leitor de QRCode ( caso você não saiba exatamente o que é um segue um link para dar uma introdução sobre o que são e como funcionam). OK vamos la nosso leitor será algo extremamente simples porem bem legal e não é tão complexo de se fazer, vamos começar com uma singleView.
Em nosso storyboard vamos inserir 1 View, 1 label e por fim 1 botão, nosso tela fica mais ou menos assim:
Ainda em nosso storyboard já vamos criar as properties , e também uma ação para nosso botão:
@property (weak, nonatomic) IBOutlet UIView *CapturaDela;
@property (weak, nonatomic) IBOutlet UILabel *status;
@property (weak, nonatomic) IBOutlet UIButton *botaoLerCodigo;
Como em nosso projeto vamos precisar acessar alguns dados sobre a câmera, vamos importar a classe AVFoundation caso não tenha sido importada ainda , e importe também o protocolo AVCaptureMetadataOutputObjectsDelegate.
Partindo para nosso .m
Antes de mais nada vamos criar 4 properties dentro de @interface ViewController ()
@property (nonatomic, strong) AVCaptureSession *captureSession;
@property (nonatomic, strong) AVCaptureVideoPreviewLayer *videoPreviewLayer;
@property (nonatomic, strong) AVAudioPlayer *audioPlayer;
@property (nonatomic) BOOL estaLendo;
Essas propertys serão as responsáveis por gravar as imagens, e também trabalham com o áudio.
Feito isso a próxima coisa a se fazer é importar nosso áudio, o beep.mp3 do download está aqui, com o nosso beep já dentro do projeto vamos desenvolver um método para que o som seja pré-carregado e que seja apenas executado quando necessário, vamos então criar nosso método preCarregarBeep, nosso método fica assim:
-(void)preCarregarBeep{
// neste metodo vai fazer o seguite, ele vai deixar nosso beep para ser executado na hora que precisar
// criamos a string que contem o nome do nosso arquivo e sua extensão
NSString *beepFilePath = [[NSBundle mainBundle] pathForResource:@”beep” ofType:@”mp3″];
// criamos agora uma NSURL usando nosso arquivo anterior
NSURL *beepURL = [NSURL URLWithString:beepFilePath];
// vamos fazer um tratamento de erros, caso não tenhamos erro com nosso arquivo vamos deixar nosso beep pronto para ser executado
NSError *error;
_audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:beepURL error:&error];
if (error) {
NSLog(@”Erro ao abrir o som”);
NSLog(@”%@”, [error localizedDescription]);
}
else{
[_audioPlayer prepareToPlay];
}
O próximo método que vamos criar é o comecarALer esse método será disparado quando o usuário clicar no botão para começar a verificar o código.
-(BOOL)comecarALer{
NSError *error;
// criamos nossas instancias de captura de imagem
AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];
if (!input) {
// Se acontecer algum erro vai dar um log no erro
NSLog(@”%@”, [error localizedDescription]);
return NO;
}
// inicia a captura de imagem
self.captureSession = [[AVCaptureSession alloc] init];
[self.captureSession addInput:input];
AVCaptureMetadataOutput *captureMetadataOutput = [[AVCaptureMetadataOutput alloc] init];
[self.captureSession addOutput:captureMetadataOutput];
// Create um novo serial dispatch queue.
dispatch_queue_t dispatchQueue;
dispatchQueue = dispatch_queue_create(“myQueue”, NULL);
[captureMetadataOutput setMetadataObjectsDelegate:self queue:dispatchQueue];
[captureMetadataOutput setMetadataObjectTypes:[NSArray arrayWithObject:AVMetadataObjectTypeQRCode]];
//inicia o video preview e atribui ele a nossa view.
_videoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_captureSession];
[_videoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
[_videoPreviewLayer setFrame:self.CapturaDela.layer.bounds];
[self.CapturaDela.layer addSublayer:_videoPreviewLayer];
// começa a captura de tela
[self.captureSession startRunning];
return YES;
}
Criamos um método do tipo booleano pois vamos nos basear na resposta do método para determinar se o código conseguiu ou não executar a leitura.
Bom já temos o método que executa nosso beep, e já temos a leitura do código o que ainda falta? Ainda precisamos que pare a leitura do código afinal se não fecharmos o acesso a camera ela ficaria ainda funcionando, então vamos la vamos criar o método parandoLeitura.
-(void)parandoLeitura{
// para a captura de video
[self.captureSession stopRunning];
self.captureSession = nil;
// Remove o preview do video da view
[self.videoPreviewLayer removeFromSuperlayer];
}
Estamos quase lá aguentem só mais um pouco, vamos ao nosso último método, e esse é o responsável por fazer a mágica, ele realiza a ligação entre o que a câmera está registrando e o que aparecerá na view.
-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{
// esse metodo é onde “ligamos” nossa camera para fazer a leitura
// checa se o metadataObjects array não é vazio, e que contem ao menos 1 objeto
if (metadataObjects != nil && [metadataObjects count] > 0) {
AVMetadataMachineReadableCodeObject *metadataObj = [metadataObjects objectAtIndex:0];
if ([[metadataObj type] isEqualToString:AVMetadataObjectTypeQRCode]) {
[self.status performSelectorOnMainThread:@selector(setText:) withObject:[metadataObj stringValue] waitUntilDone:NO];
[self performSelectorOnMainThread:@selector(parandoLeitura) withObject:nil waitUntilDone:NO];
[self.botaoLerCodigo performSelectorOnMainThread:@selector(setTitle:) withObject:@”Start!” waitUntilDone:NO];
self.estaLendo = NO;
// lembra do primeiro metodo que criamos, então agora que utilizamo ele
// verifica se nosso audio não for nil executa o som
if (_audioPlayer) {
[_audioPlayer play];
}
}
}
}
Bom pessoal é isso, já temos todos os métodos criados, vamos “chama-los”, lembram da action que criamos no início do projeto dentro dele chamaremos os métodos que acabamos de criar nossa action ficou da seguinte maneira.
– (IBAction)lerCodigo:(UIButton *)sender {
// precisamos primeiramente verificar se nosso usuario já não esta lendo algum código
if (!_estaLendo) {
if ([self comecarALer]) {
self.botaoLerCodigo.enabled = NO;
self.status.text = @”Escaneando código”;
}else{
[self parandoLeitura];
}
}
// inverte o valor de nosso booleano para que nossa action possa ser executa de novo
self.estaLendo = !self.estaLendo;
}
Agora só falta testar o código, lembrando que o código não pode ser testado no simulador pois o simulador não tem camera instalado no simulador faça um teste e tente ler o QRCode abaixo:
Esse é o link para o download do projeto completo.
Objective-C
Xcode 6.1
iOS 8.1