iOS 扫一扫
利用系统自带框架实现扫一扫功能
一 项目配置
扫一扫功能相机和相册权限,在info.plist中设置询问用户是否允许访问的权限。
info.plist加入NSCameraUsageDescription、NSPhotoLibraryUsageDescription、NSPhotoLibraryAddUsageDescription
<key>NSCameraUsageDescription</key>
<string>开启相机权限,活动扫一扫更快捷</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>添加照片需要您的同意</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>开启照片权限,美照当然要人赞!</string>
二 扫一扫权限判断
当每次进入扫一扫页面时,需要判断是否开启了权限
/** 校验是否有相机权限 */
- (void)checkCameraAuthorizationStatus:(void(^)(BOOL granted))permissionGranted
{
AVAuthorizationStatus videoAuthStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
switch (videoAuthStatus) {
// 已授权
case AVAuthorizationStatusAuthorized:
{
permissionGranted(YES);
}
break;
// 未询问用户是否授权
case AVAuthorizationStatusNotDetermined:
{
// 提示用户授权
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
permissionGranted(granted);
}];
}
break;
// 用户拒绝授权或权限受限
case AVAuthorizationStatusRestricted:
case AVAuthorizationStatusDenied:
{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"请在”设置-隐私-相机”选项中,允许访问你的相机" message:nil delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil];
[alert show];
permissionGranted(NO);
}
break;
default:
break;
}
}
三 需要用到AVCaptureDevice、AVCaptureDeviceInput、AVCaptureMetadataOutput、AVCaptureSession、AVCaptureVideoPreviewLayer
- AVCaptureDevice:捕获设备,通常是前置摄像头,后置摄像头,麦克风(音频输入)
- AVCaptureDeviceInput:AVCaptureDeviceInput 代表输入设备,使用AVCaptureDevice 来初始化
- AVCaptureMetadataOutput:输出
- AVCaptureSession:session 把输入输出结合在一起,并开始启动捕获设备(摄像头)
- AVCaptureVideoPreviewLayer:图像预览层,实时显示捕获的图像
设置相机
/**
设置相机
*/
- (void)setupCamera {
self.avDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
self.avInput = [AVCaptureDeviceInput deviceInputWithDevice:self.avDevice error:nil];
self.avOutput = [[AVCaptureMetadataOutput alloc]init];
[self.avOutput setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
self.avSession = [[AVCaptureSession alloc]init];
[self.avSession setSessionPreset:AVCaptureSessionPresetHigh];
if ([self.avSession canAddInput:self.avInput]){
[self.avSession addInput:self.avInput];
}
if ([self.avSession canAddOutput:self.avOutput]){
[self.avSession addOutput:self.avOutput];
}
// 二维码类型 AVMetadataObjectTypeQRCode
if ([self.avOutput.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeQRCode]){
self.avOutput.metadataObjectTypes = [NSArray arrayWithObject:AVMetadataObjectTypeQRCode];
// AVMetadataObjectTypeAztecCode 条形码
} else{
return ;
}
[self.avSession startRunning];//开始扫描
}
返回预览layer
/**
显示的预览layer
@return AVCaptureVideoPreviewLayer
*/
- (AVCaptureVideoPreviewLayer *)showPeviewLayer {
self.avPreviewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.avSession];
self.avPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
return self.avPreviewLayer;
}
开始扫描与结束扫描
/**
开始扫描
*/
- (void)startRunning {
[self.avSession startRunning];
}
/**
结束扫描
*/
- (void)stopRunning {
[self.avSession stopRunning];
}
输出扫描结果AVCaptureMetadataOutputObjectsDelegate
#pragma mark - AVCaptureMetadataOutputObjectsDelegate
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:
(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
if ([metadataObjects count] > 0){
AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex:0];
NSString *result = metadataObject.stringValue;//扫描出来的字符串
NSLog(@"result:%@",result);
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"显示扫描结果" message:result delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil];
[alert show];
[self.avSession stopRunning];//停止扫描
}
}
使用
self.scanConfig = [[INQrScanConfig alloc] init];
[self.scanConfig setupCamera];
AVCaptureVideoPreviewLayer *previewLayer = [self.scanConfig showPeviewLayer];
previewLayer.frame = self.layer.bounds;
[self.layer insertSublayer:previewLayer atIndex:0];
[self.scanConfig startRunning];
使用
//你要设置的矩形快的frame 为 x1, y1, w1, h1.
//那么你的 rectOfInterest 应该设置为 (y1/h, x1/w, h1/h, w1/w)
CGFloat size = 260.0;
CGRect rect = CGRectMake((KAiSysScreenWidth - size)/2, (KAiSysScreenHeight - size)/2, size, size);
// 使用 (y1/h, x1/w, h1/h, w1/w)
self.avOutput.rectOfInterest = CGRectMake(rect.origin.y/KAiSysScreenHeight, rect.origin.x/KAiSysScreenWidth, size/KAiSysScreenHeight, size/KAiSysScreenWidth);
结果如图: