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];}// 二维码类型 AVMetadataObjectTypeQRCodeif ([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);
结果如图: