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
頭部記得導入代理<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即可。
希望能幫到大家。