iOS|iOS 原生扫码二维码与自定义相机

实现扫码二维码与自定义相机的功能,都要用到 AVFoundation 框架。
完成功能后发现,这俩个功能在实现上大致相同,唯一不同的地方是 设置 AVCaptureSession 的 output。
扫描二维码

self.metadataOutput = [AVCaptureMetadataOutput new]; //输出的类 为 AVCaptureMetadataOutput [self.session addOutput:self.metadataOutput]; self.metadataOutput.metadataObjectTypes = @[ AVMetadataObjectTypeQRCode, ]; [self.metadataOutput setMetadataObjectsDelegate:self queue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)]; //可以通过设置 rectOfInterest 属性,来调整扫码区域。

自定义相机
self.photoOutput = [[AVCapturePhotoOutput alloc] init]; //输出的类 为 AVCapturePhotoOutput NSDictionary *setDic = @{ AVVideoCodecKey:AVVideoCodecTypeJPEG, }; self.photoSettings = [AVCapturePhotoSettings photoSettingsWithFormat:setDic]; [self.photoOutput setPhotoSettingsForSceneMonitoring:self.photoSettings]; [self.session addOutput:self.photoOutput]; //可以通过设置 rectOfInterest 属性,来调整扫码区域。

具体实现如下:
首先,添加如下属性
@interface XXXCaptureViewController ()@property (nonatomic, assign)BOOL currentAuthStatus; @property (nonatomic, strong)AVCaptureDevice *device; @property (nonatomic, strong)AVCaptureSession *session; @property (nonatomic, strong)AVCaptureDeviceInput *input; @property (nonatomic, strong)AVCaptureMetadataOutput *metadataOutput; @property (nonatomic, strong)AVCapturePhotoOutput *photoOutput; @property (nonatomic, strong)AVCapturePhotoSettings *photoSettings; @property (nonatomic, strong)UIButton *takephotoButton;

在使用相机前,要查看是否授权
- (BOOL)authStatus { AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]; if (authStatus == AVAuthorizationStatusAuthorized) { return YES; } else { return NO; } }

如果该 App 没有授权相机功能,需要请求授权
__block typeof(self) weakSelf = self; [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {if (granted == NO) { weakSelf.currentAuthStatus = NO; } else { weakSelf.currentAuthStatus = YES; [weakSelf configureCaptureSessionSettting]; }

然后添加属性的相关设置
- (void)configureCaptureSessionSettting { if (self.currentAuthStatus == NO) { return; }self.session = [AVCaptureSession new]; self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; NSError *error; self.input = [AVCaptureDeviceInputdeviceInputWithDevice:self.device error:&error]; [self.session addInput:self.input]; //扫二维码 //[self.session addOutput:self.metadataOutput]; //self.metadataOutput.metadataObjectTypes = @[ //AVMetadataObjectTypeQRCode,//可以添加 AVMetadataObjectTypeCode39Code 等类型同时扫描条形码 //]; //[self.metadataOutput setMetadataObjectsDelegate:self queue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)]; //捕获照片 self.photoOutput = [[AVCapturePhotoOutput alloc] init]; NSDictionary *setDic = @{ AVVideoCodecKey:AVVideoCodecTypeJPEG, }; self.photoSettings = [AVCapturePhotoSettings photoSettingsWithFormat:setDic]; [self.photoOutput setPhotoSettingsForSceneMonitoring:self.photoSettings]; [self.session addOutput:self.photoOutput]; AVCaptureVideoPreviewLayer* previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.session]; previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; dispatch_async(dispatch_get_main_queue(), ^{[previewLayer setFrame:self.view.bounds]; [self.view.layer insertSublayer:previewLayer atIndex:0]; }); }

【iOS|iOS 原生扫码二维码与自定义相机】最后一步啦,开始捕获数据和停止补货。最好不要把它们放在主线程中使用。因为 startRunning 和 stopRunning 其实是一个 block,主线程调用可能会引起,UI卡顿。苹果官方具体解释:https://developer.apple.com/documentation/avfoundation/avcapturesession
- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{[self.session startRunning]; }); } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{[self.session stopRunning]; }); }

    推荐阅读