iOS原生封裝二維碼、條形碼掃描工具;生成、識別(彩色)二維碼、條形碼圖片

二維碼掃描在App中很常見的功能,之前都是用三方工具Zing、ZBar。后來Apple的AVFoundation也支持二維碼掃描、生成,而且效率比三方庫還要高。我把它封裝成一個工具,這樣使用起來十分方便,同時還封裝了掃描視圖,在工程中增加掃描更加快捷。

主要使用AVCaptureSession鏈接攝像頭進行采集信息
Coding~

//初始化鏈接對象
self.session = [[AVCaptureSession alloc]init];
//高質量采集率
[self.session setSessionPreset:AVCaptureSessionPresetHigh];
//獲取攝像設備
self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
//創建輸入流
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];
//添加輸入流
if ([self.session canAddInput:input]) {
    [self.session addInput:input];
}
//創建輸出流
self.output = [[AVCaptureMetadataOutput alloc] init];
//設置代理在主線程里刷新(Tip:如果封裝的類不是單利或者全局變量,代理AVCaptureMetadataOutputObjectsDelegated不會被調用)
[self.output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
//添加輸出流
if ([self.session canAddOutput:self.output]) {
    [self.session addOutput:self.output];
}
//設置掃碼支持的編碼格式,Tip:必須在添加輸出流之后
if ([self.output availableMetadataObjectTypes].count) {
    if (scanType == ZHBarScanTypeQRCode) {
        self.output.metadataObjectTypes = @[AVMetadataObjectTypeQRCode];
    } else if (scanType == ZHBarScanTypeBarCode) {
        self.output.metadataObjectTypes = @[AVMetadataObjectTypeEAN13Code,
                                            AVMetadataObjectTypeEAN8Code,
                                            AVMetadataObjectTypeCode128Code];
    } else {
        self.output.metadataObjectTypes = @[AVMetadataObjectTypeQRCode,
                                            AVMetadataObjectTypeEAN13Code,
                                            AVMetadataObjectTypeEAN8Code,
                                            AVMetadataObjectTypeCode128Code];
    }
}
//設置有效的掃描區域,Tip:rectOfInterest是比值,默認為CGRectMake(0, 0, 1, 1)
/* 手動計算
 計算為CGRectMake(y1/h, x1/w, h1/h, w1/w);
 y1,x1,h1,w1為掃描區域的frame,h,w是layer視圖的寬高
 手動計算要在session運行前設置
 */

/* 自動轉換
 - (CGRect)metadataOutputRectOfInterestForRect:(CGRect)rectInLayerCoordinatesl;
 這個方法可以把掃描區域的frame轉成rectOfInterest的坐標系
 這個方法必須在session運行后設置
 */

//如果傳入的scanArea的寬不大于1,說明是手動計算
if (scanRect.size.width <= 1) {
    self.output.rectOfInterest = scanRect;
}
//創建相機渲染層
self.layer = [AVCaptureVideoPreviewLayer layerWithSession:self.session];
self.layer.videoGravity = AVLayerVideoGravityResizeAspectFill;
self.layer.frame = layerView.layer.bounds;
[layerView.layer insertSublayer:self.layer atIndex:0];

[ZHBarTool requestCameraAuthorizedResult:^(BOOL granted) {
    if (granted) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.session startRunning];
            self.isAvailable = YES;
            self.scanInterval = self.scanInterval ? self.scanInterval : 2;
            //如果傳入的scanArea的寬大于1,調用系統方法轉換
            if (scanRect.size.width > 1) {
                self.scanRect = scanRect;
                CGRect rectOfInterest = [self.layer metadataOutputRectOfInterestForRect:scanRect];
                self.output.rectOfInterest = rectOfInterest;
            }
        });
    } else {
        if ([self.delegate respondsToSelector:@selector(ZHBarAuthorizedCameraFailed)]) {
            [self.delegate ZHBarAuthorizedCameraFailed];
        }
        if (self.authorizedCameraFailed) {
            self.authorizedCameraFailed();
        }
    }
}];

注意點:

有效的掃描區域:rectOfInterest。這是個比值,而且坐標系和我們平常開發使用的不一樣,計算時需要轉化,不過系統給我們提供了方法

- (CGRect)metadataOutputRectOfInterestForRect:(CGRect)rectInLayerCoordinatesl;

可以轉化我們熟悉的坐標系下的frame為rectOfInterest需要的坐標,但使用這個方法必須在session啟動之后設置。

代理:

- (void)captureOutput:(AVCaptureOutput *)output didOutputMetadataObjects:(NSArray<__kindof AVMetadataObject *> *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
AVMetadataMachineReadableCodeObject *object = [metadataObjects objectAtIndex:0];
NSString *obj = [object stringValue];
}

二維碼條形碼生成

主要使用過濾器CIFilter
//二維碼過濾器
CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
/條形碼過濾器
CIFilter *filter = [CIFilter filterWithName:@"CICode128BarcodeGenerator"];

解析二維碼圖片

NSString *url = nil;
//初始化一個監測器
CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{CIDetectorAccuracy:CIDetectorAccuracyHigh}];
//監測到的結果數組
NSArray *features = [detector featuresInImage:[CIImage imageWithCGImage:aImage.CGImage]];
if (features.count >=1) {
    //結果對象
    CIQRCodeFeature *feature = [features objectAtIndex:0];
    NSString *result = feature.messageString;
    url = result;
}

解析條形碼圖片

很遺憾╮(╯_╰)原生還不支持解析條形碼圖片,如果有需要的話只能使用三方庫了。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 關于二維碼(或者條形碼,以下歸類簡稱二維碼)掃描和生成的,我相信網絡上相關的文章層數不窮,但是,大部分都是直接粘貼...
    FR_Zhang閱讀 6,717評論 10 42
  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,200評論 4 61
  • **申明** 由于用簡書寫代碼有很多代碼會無緣無故消失掉,所以才用了圖片的方式 *以下重新補發鏈接* [后盾網](...
    Jiang鋒時刻閱讀 286評論 0 0
  • 文 / IDO老徐原創文章,禁止轉載;轉發、分享隨意。 繼上次分享簡歷&面試后,今天繼續分享面試話題分享IDO老徐...
    IDO老徐閱讀 2,366評論 11 20
  • 話說這李澤言雖然心里犯著嘀咕,但是還是如約大半夜來到了老師房間前。 正要敲門呢,房間里傳來一個聲音,進來吧,門沒鎖...
    十月sep閱讀 920評論 1 1