iOS_二維碼掃描(iOS自帶)

iOS7開始,不需要第三方也能進行二維碼掃描了。

之前用過ZBar這個第三方包,後來iOS版本高了用不了,貌似我下的那個包只支持32位。

應該還有其他版本的支持,只是後來沒用到就沒去找了。

今天研究了一下系統自帶的二維碼掃描,掃描速度很快。

肚子餓,節約點時間直接上代碼,因怎麼用我也有註釋了。大家根據需要看看響應的代碼吧。


首先,導入

#import <AVFoundation/AVFoundation.h>

Ps:自己練習的時候,順便複習了一下block傳值和代理傳值,在此代碼也一起上了吧,不懂的可以看看,自己也權當做個筆記。

先附上掃描VC的.h代碼

#import </span>"BaseVC.h"
//該viewController是繼承BaseVC(ViewController)創建<pre name="code" class="objc">
@protocol ScanDelegate <NSObject>//添加代理方法(默認情況下必須實現)- (void)setStringValue:(NSString *)stringValue;@optional//可選的方法@end@interface ScanVC : BaseVC//block傳值@property (strong, nonatomic) void (^stringValue)(NSString *value);//代理傳值@property (strong, nonatomic) id<ScanDelegate>delegate;@end

以下爲.m的代碼

#import "ScanVC.h"
#import <AVFoundation/AVFoundation.h>

@interface ScanVC ()<AVCaptureMetadataOutputObjectsDelegate>

//**
@property (strong, nonatomic) AVCaptureSession *captureSession;
@property (strong, nonatomic) AVCaptureVideoPreviewLayer *videoPreviewLayer;
@property (strong, nonatomic) AVCaptureMetadataOutput *captureMetadataOutput;
@property (strong, nonatomic) UIView *viewPreview;//掃描窗口

@end

@implementation ScanVC

- (void)viewDidLoad {
    [super viewDidLoad];
    /**
     CaptureSession 這是個捕獲會話,也就是說你可以用這個對象從輸入設備捕獲數據流。
     AVCaptureVideoPreviewLayer 可以通過輸出設備展示被捕獲的數據流。
     首先,應該判斷當前設備是否有捕獲數據流的設備。
     */
    NSError *error;
    AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];
    
    if (!input) {
        NSLog(@"%@", [error localizedDescription]);
    }else{
        //設置會話的輸入設備
        if (!_captureSession) {
            _captureSession = [[AVCaptureSession alloc] init];
        }
        [_captureSession addInput:input];
        
        //對應輸出
        if (!_captureMetadataOutput) {
            _captureMetadataOutput = [[AVCaptureMetadataOutput alloc] init];
        }
        [_captureSession addOutput:_captureMetadataOutput];
        
        //創建一個隊列
        dispatch_queue_t dispatchQueue;
        dispatchQueue = dispatch_queue_create("myQueue",NULL);
        [_captureMetadataOutput setMetadataObjectsDelegate:self queue:dispatchQueue];
        [_captureMetadataOutput setMetadataObjectTypes:[NSArray arrayWithObject:AVMetadataObjectTypeQRCode]];//設置條碼類型。更多類型底下補上
        
        //降捕獲的數據流展現出來
        _videoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_captureSession];
        [_videoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
        
        if (!_viewPreview) {
            _viewPreview = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 320, 320)];
            [self.view addSubview:_viewPreview];
        }        
        [_videoPreviewLayer setFrame:_viewPreview.layer.bounds];
        [_viewPreview.layer addSublayer:_videoPreviewLayer];
        
        //開始捕獲
        [_captureSession startRunning];
    }
}

//獲得的數據在 AVCaptureMetadataOutputObjectsDelegate 唯一定義的方法中
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{
    //判斷是否有數據,是否是二維碼數據
    if (metadataObjects != nil && [metadataObjects count] > 0) {
        AVMetadataMachineReadableCodeObject *metadataObj = [metadataObjects objectAtIndex:0];
        if ([[metadataObj type] isEqualToString:AVMetadataObjectTypeQRCode]) {
            //獲得掃描的數據,並結束掃描
            [self performSelectorOnMainThread:@selector(stopReading:)withObject:metadataObj.stringValue waitUntilDone:NO];
            //線程更新label的text值
//            [_result performSelectorOnMainThread:@selector(setText:) withObject:metadataObj.stringValue waitUntilDone:NO];
            //block傳值
            _stringValue(metadataObj.stringValue);
            //代理傳值
            [_delegate setStringValue:metadataObj.stringValue];
        }
    }
}

- (void)stopReading:(id)sender{
    [_captureSession stopRunning];
    _captureSession = nil;
    [_videoPreviewLayer removeFromSuperlayer];
    
    [self.navigationController popViewControllerAnimated:YES];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
@end


掃描類型補充:

AVMetadataObjectTypeQRCode,

AVMetadataObjectTypeCode128Code,

AVMetadataObjectTypeEAN8Code,

AVMetadataObjectTypeUPCECode,

AVMetadataObjectTypeCode39Code,

AVMetadataObjectTypePDF417Code,

AVMetadataObjectTypeAztecCode,

AVMetadataObjectTypeCode93Code,

AVMetadataObjectTypeEAN13Code,

AVMetadataObjectTypeCode39Mod43Code


掃描的代碼就這些了,以下爲上一個VC接收block值和代理傳過來的值:

頭部記得導入代理<ScanDelegate>(自定義)

</pre><pre>
#pragma mark - 二維碼掃描
//掃描
- (void)scan:(BaseBtn *)button{
    
    ScanVC *scanVC = [[ScanVC alloc]init];
    
    //block 方法
    [scanVC setStringValue:^(NSString *value) {
        NSLog(@"%@",value);
    }];
    //設置代理
    scanVC.delegate = self;
    [self.navigationController pushViewController:scanVC animated:YES];
}
//代理傳值
- (void)setStringValue:(NSString *)stringValue{
    [_result performSelectorOnMainThread:@selector(setText:) withObject:stringValue waitUntilDone:NO];
}



這段代碼測試能獲取到二維碼的內容,一維碼好像不能掃描,應該跟我的條碼類型設置有關係。

找到比較多的條碼類型,也在上邊進行補充了,只是沒有進行更多測試,有興趣的可以自己去試試哈。

補充一下:

我遇到的問題:當前A_VC調用掃描的時候,結束後控件會卡住,不能進行任何操作。

我的解決方法:切換到另一個B_VC進行掃描,結束時返回當前A_VC控件就不會卡住,若要再次掃描再次進入B_VC即可。

希望能幫到大家。

發佈了29 篇原創文章 · 獲贊 8 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章