最近需要用到二维码的扫描,发现苹果有自己的原生的api,这里简单介绍一下.
首先需要引入AVFoundation.framework 库
在相应的viewController里边引入头文件.
#import
//遵守代理
@interface ScanViewController ()<AVCaptureMetadataOutputObjectsDelegate>
@property (nonatomic,strong)AVCaptureSession *captureSession;//输入输出的中间桥梁
@end
接下来就是进行二维码的扫描
#pragma mark - 开始扫描
/**
* 开始扫描
*/
- (void)beginScanning
{
//获取摄像设备
AVCaptureDevice *device = [AVCaptureDevicedefaultDeviceWithMediaType:AVMediaTypeVideo];
//创建输入流
AVCaptureDeviceInput * input = [AVCaptureDeviceInputdeviceInputWithDevice:deviceerror:nil];
if (!input)
return;
//创建输出流
AVCaptureMetadataOutput * output = [[AVCaptureMetadataOutputalloc]init];
//设置代理在主线程里刷新
[output setMetadataObjectsDelegate:selfqueue:dispatch_get_main_queue()];
//设置有效扫描区域
output.rectOfInterest = CGRectMake(0,0.5,0,0);
//初始化链接对象
self.session = [[AVCaptureSessionalloc]init];
//高质量采集率
[self.sessionsetSessionPreset:AVCaptureSessionPresetHigh];
[self.sessionaddInput:input];
[self.sessionaddOutput:output];
//设置扫码支持的编码格式(如下设置条形码和二维码兼容)
output.metadataObjectTypes =@[AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN13Code,AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code];
AVCaptureVideoPreviewLayer *layer = [AVCaptureVideoPreviewLayerlayerWithSession:self.session];
layer.videoGravity =AVLayerVideoGravityResizeAspectFill;
layer.frame = self.view.layer.bounds;
[self.view.layerinsertSublayer:layer atIndex:0];
//开始捕获
[self.sessionstartRunning];
}
/**
* 扫描的输出结果
*
* @param metadataObjects 扫描到的数据
*/
-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
if (metadataObjects.count >0) {
[self.sessionstopRunning];
AVMetadataMachineReadableCodeObject *metadataObject = [metadataObjectsobjectAtIndex:0];
UIAlertView *alert = [[UIAlertViewalloc] initWithTitle:@"扫描结果"message:metadataObject.stringValuedelegate:selfcancelButtonTitle:@"退出"otherButtonTitles:@"再次扫描",nil];
[alert show];
}
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0) {
[self.navigationControllerpopViewControllerAnimated:YES];
} else if (buttonIndex ==1) {
[self.sessionstartRunning];
}
}
AVCaptureMetadataOutput类中有一个这样的属性(在IOS7.0之后可用):
@property(nonatomic) CGRect rectOfInterest;
这个属性大致意思就是告诉系统它需要注意的区域,大部分APP的扫码UI中都会有一个框,提醒你将条形码放入那个区域,这个属性的作用就在这里,它可以设置一个范围,只处理在这个范围内捕获到的图像的信息。在使用这个属性的时候。需要几点注意:
1、这个CGRect参数和普通的Rect范围不太一样,它的四个值的范围都是0-1,表示比例。
2、经过测试发现,这个参数里面的x对应的恰恰是距离左上角的垂直距离,y对应的是距离左上角的水平距离。
3、宽度和高度设置的情况也是类似。
3、举个例子如果我们想让扫描的处理区域是屏幕的下半部分,我们这样设置
1
|
output.rectOfInterest=CGRectMake(0.5,0,0.5, 1);
|
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
// 1.初始化相册拾取器
UIImagePickerController *controller = [[UIImagePickerController alloc] init];
// 2.设置代理
controller.delegate = self;
// 3.设置资源:
controller.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
controller.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentViewController:controller animated:YES completion:NULL];
} else {
UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"提示" message:@"设备不支持访问相册,请在设置->隐私->照片中进行设置!" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
[alert show];
}
/**
* 从相册选取图片监听
*/
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
//1.获取选择的图片
UIImage *image = info[UIImagePickerControllerOriginalImage];
//2.初始化一个监测器
CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{ CIDetectorAccuracy : CIDetectorAccuracyHigh }];
[picker dismissViewControllerAnimated:YES completion:^{
//监测到的结果数组
NSArray *features = [detector featuresInImage:[CIImage imageWithCGImage:image.CGImage]];
if (features.count > 0) {
/**结果对象 */
CIQRCodeFeature *feature = [features objectAtIndex:0];
NSString *scannedResult = feature.messageString;
UIAlertView * alertView = [[UIAlertView alloc]initWithTitle:@"扫描结果" message:scannedResult delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
[alertView show];
}
else{
UIAlertView * alertView = [[UIAlertView alloc]initWithTitle:@"提示" message:@"该图片没有包含一个二维码!" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
[alertView show];
}
}];
}