ios-實現二維碼掃描功能
阿新 • • 發佈:2019-02-10
在此就簡單的介紹下二維碼掃描功能的實現把
首先先說下思路,我們需要去配置的就是
1、輸入裝置(用來獲取外界資訊),輸入裝置有攝像頭、麥克風、鍵盤
2、輸出裝置(將收集到的資訊進行解析去獲取收到的內容)
3、會話的session(用來連線輸入和輸出的裝置),不然的話你輸入和輸出裝置都是獨立的沒有個連線
4、展示輸入裝置所採集的資訊
我們可以定義以下的屬性
之後就是進行建立操作//1、輸入裝置(用來獲取外界資訊),輸入裝置有攝像頭、麥克風、鍵盤 @property (nonatomic ,strong)AVCaptureDeviceInput *input; //2、輸出裝置(將收集到的資訊進行解析去獲取收到的內容) @property (nonatomic ,strong)AVCaptureMetadataOutput *output; //3、會話的session(用來連線輸入和輸出的裝置) /** AVCaptureSession(捕捉會話管理):它從物理裝置得到資料流(比如攝像頭和麥克風),然後輸出,它可以通過來控制捕捉資料的格式和質量 */ @property (nonatomic ,strong)AVCaptureSession *session; //4、展示輸入裝置所採集的資訊,也就是被用於自動顯示相機產生的實時影象 @property (nonatomic ,strong)AVCaptureVideoPreviewLayer *previewlayer;
這裡需要注意的就是設定掃描區域的大小,它的預設掃描區域時全屏,預設值是(0,0,1,1)- (IBAction)ScanClick:(id)sender { //首先先判斷輸入裝置是否可用,獲取的是攝像頭裝置 AVCaptureDevice * device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; if(device==nil) { //設定彈出alertController UIAlertController * alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"裝置沒有攝像頭" preferredStyle: UIAlertControllerStyleAlert]; [alert addAction:[UIAlertAction actionWithTitle:@"確認" style: UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { }]]; [self presentViewController:alert animated:YES completion:nil]; return; } //1、輸入裝置(用來獲取外界資訊) self.input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil]; //2、輸出裝置(將收集到的資訊進行解析去獲取收到的內容) self.output = [AVCaptureMetadataOutput new]; //3、會話的session(用來連線輸入和輸出的裝置) self.session = [AVCaptureSession new]; //用於設定output輸出流的bitrate或者說採集的質量 if([self.session canSetSessionPreset:AVCaptureSessionPresetHigh]) { [self.session setSessionPreset:AVCaptureSessionPresetHigh]; } //捕捉會話管理和輸入輸出裝置進行關聯 if([self.session canAddInput:self.input]) { [self.session addInput:self.input]; } if([self.session canAddOutput:self.output]) { [self.session addOutput:self.output]; } //指定輸出裝置的代理,用來接收返回的資料,回撥在主佇列中執行 [self.output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()]; //設定元資料型別 二維碼就是QRCode [self.output setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]]; //設定掃描區域的大小 CGFloat Width = self.view.bounds.size.width; CGFloat Height = self.view.bounds.size.height; [self.output setRectOfInterest:CGRectMake((Height*0.5 - 140)/Height,(Width * 0.5 - 140)/Width, 280/Height, 280/Width)]; //4、特殊的layer(展示輸入的裝置所採集的資訊),可被用於自動顯示相機產生的實時影象 self.previewlayer = [[AVCaptureVideoPreviewLayer alloc]initWithSession:_session]; //設定layer的大小, self.previewlayer.frame = self.view.bounds; //新增layer [self.view.layer addSublayer:self.previewlayer]; //啟動會話 [self.session startRunning]; } //獲取掃描的結果 -(void)captureOutput:(AVCaptureOutput *)output didOutputMetadataObjects:(NSArray<__kindof AVMetadataObject *> *)metadataObjects fromConnection:(AVCaptureConnection *)connection { //1、停止會話 [self.session stopRunning]; //2、刪除layer [self.previewlayer removeFromSuperlayer]; //3、遍歷資料獲取內容 for(AVMetadataMachineReadableCodeObject * obj in metadataObjects) { self.detailLabel.text = obj.stringValue; } //captureOutput: 輸出裝置的意思 //metadataObjects: 元資料物件的陣列 //connection: 連線 }
如下圖所示
如果我們要去設定掃描區域的大小也就是去設定setRectOfInterest,裡面傳入的CGRect的x和y和w和h都是0-1。
這裡需要注意的是我們這裡傳入的應該的四個引數應該是Y,X,H,W,右上角是原點,如下圖所示
這裡還有一點需要介紹的是
這裡傳入的陣列多加了個__kindof,__kindof:代表這個數組裡面可以有它本身的類也可以有它的子類,也會被用在方法的返回值,加__kindof修飾後,比如說一個方法的返回值原本是NSArray,但是方法裡邊卻返回了一個NSArray的子類
NSMutableArray,也就是說,加__kindof修飾後,本類及其子類都可以返回,呼叫使用時也可以使用本類或者
子類去接收方法的返回值。我們可以看到蘋果對於下面這個方法來說,返回值也是加了__kindof
- (nullable __kindof UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier;
還有一點要補充的就是下面這個方法
+ (Class)layerClass
{
return [AVCaptureVideoPreviewLayer class];
}
每一個UIView都有在一個CALayer,這個圖層是由檢視自動建立和管理的,一旦檢視被建立,我們就無法去更改這個layer了。但是如果我們自定義一個view,那我們就可以重寫+layerClass方法使得在建立的時候能返回一個不同的圖層的子類。UIView會在初始化的時候呼叫+layerClass方法,然後用它的返回型別來建立view的layer。