1. 程式人生 > >使用系統提供的AVFoundation 實現二維碼掃描(帶動畫)

使用系統提供的AVFoundation 實現二維碼掃描(帶動畫)

注意這裡的掃描必須真機測試

模擬器上是看不出來效果的

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

@interface ViewController ()<AVCaptureMetadataOutputObjectsDelegate>

//輸入和輸出裝置的橋樑
@property (nonatomic, strong) AVCaptureSession *session;

/**
 *  <#Description#>
 */
@property (nonatomic, weak) UIImageView *backgroundImageView;

/**
 *  線
 */
@property (nonatomic, weak) UIImageView *scanLineImageView;

@end

@implementation ViewController

- (UIImageView *)scanLineImageView
{
    if (!_scanLineImageView)
    {
        UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"qr_scan_line"]];
        imageView.frame = CGRectMake(0, 0, self.backgroundImageView.frame.size.width, 1);
        [self.backgroundImageView addSubview:imageView];
        
        _scanLineImageView = imageView;
    }
    
    return _scanLineImageView;
}

- (UIImageView *)backgroundImageView
{
    if (!_backgroundImageView)
    {
        int space = 40;
        
        UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"smk"]];
        imageView.frame = CGRectMake(space, space, self.view.frame.size.width - 2 * space, self.view.frame.size.width - 2 * space);
        [self.view addSubview:imageView];
        
        _backgroundImageView = imageView;
    }
    
    return _backgroundImageView;
}

- (AVCaptureSession *)session
{
    if (!_session)
    {
        _session = [[AVCaptureSession alloc] init];
    }
    
    return _session;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    /*
     AVCaptureDevice 裝置
     AVCaptureDeviceInput 輸入裝置
     AVCaptureMetadataOutput 輸出裝置
     AVCaptureSession 輸入和輸出裝置的橋樑,負責input和output資料互動。
     */
    
    

  
}

/**
 *  開始掃描
 *
 *  @param sender <#sender description#>
 */
- (IBAction)startScan:(id)sender
{
    if (!_session)
    {
        //1.裝置
        AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        
        //2.輸入裝置
        AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
        
        //3.輸出裝置
        AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];
        //設定代理
        [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
        
<pre name="code" class="objc">        output.metadataObjectTypes = @[AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code];

//4.輸入和輸出裝置的橋樑,負責input和output資料互動 if ([self.session canAddInput:input]) { //新增輸入裝置 [self.session addInput:input]; } if ([self.session canAddOutput:output]) { //新增輸出裝置 [self.session addOutput:output]; } //可用型別 //[output availableMetadataObjectTypes]; //5. /* AVMetadataObjectTypeQRCode 二維碼 */ //6.初始化要顯示影象的layer //顯示拍攝視訊影象 AVCaptureVideoPreviewLayer *layer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.session]; layer.frame = self.view.bounds; layer.contentsGravity = kCAGravityResizeAspectFill; [self.view.layer insertSublayer:layer atIndex:0]; } //7.開始掃描 [self.session startRunning]; [self animationScan];}#pragma mark - 代理方法(可能會呼叫多次)- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{ //掃描成功 if (metadataObjects.count > 0) { //如果掃描成功就停止掃描 [self.session stopRunning]; //結果類 AVMetadataMachineReadableCodeObject *object = metadataObjects[0]; //獲取掃描的資料 NSString *value = [object stringValue]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:value delegate:nil cancelButtonTitle:@"Cancel" otherButtonTitles:nil, nil]; [alert show]; } }#pragma mark -/** * 掃描動畫 */- (void)animationScan{ [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(updateScanLineFrame) userInfo:nil repeats:YES];}bool upMove;/** * 更新線的座標 */- (void)updateScanLineFrame{ if (self.scanLineImageView.frame.origin.y <= 20) { //向下移動 upMove = NO; } else if(self.scanLineImageView.frame.origin.y >= self.backgroundImageView.frame.size.height - 20) { //向上移動 upMove = YES; } CGRect frame = self.scanLineImageView.frame; if (upMove) { frame.origin.y--; } else { frame.origin.y++; } //重新修改座標 self.scanLineImageView.frame = frame; }- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.}@end