掃描二維碼、條形碼,生成二維碼


title: iOS二維碼操做
date: 2016-05-11 16:51:31ios

iOS-ScanningCode

功能:掃描二維碼、條形碼,生成二維碼。具體使用請看項目。github地址 喜歡的朋友們給個星星吧。萌萌噠。git

  • Image Displey(圖片展現)

圖片名稱

圖片名稱

圖片名稱

圖片名稱

使用方法

  • 首先,你須要把項目中的XYLScaningCodeKit文件夾拖拽到你的項目任意位置,而後就能夠開始使用了。
  • 添加二維碼界面github

    假如你須要在項目中須要使用生成二維碼的功能,僅僅須要引入頭文件和建立二維碼視圖並添加就能夠了。例如這樣:session

#import "XYLScaningCode.h"

@interface ViewController ()
@property(strong, nonatomic)XYLBinaryCodeView *binaryCodeView;  //二維碼界面
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor blackColor];
    //設置生成二維碼界面
    self.binaryCodeView = [[XYLBinaryCodeView alloc]initWithFrame:[UIScreen mainScreen].bounds];
    //設置二維碼的內容
    self.binaryCodeView.inputData = @"www.baidu.com";
    [self.view insertSubview:self.binaryCodeView atIndex:1];
}
  • 添加掃描二維碼、條形碼功能框架

    假如你須要使用掃碼的功能,那代碼稍微多一點點,多的部分就是開始掃碼、讀取掃碼結果、處理掃碼結果那部分。ide

    一樣的,你也須要引入上面的頭文件;atom

    而後就是一些邏輯了,不用太擔憂,由於我會有不少的註釋,並且後面還會詳細分析。代碼以下:spa

#import "ViewController.h"
#import "XYLScaningCode.h"

@interface ViewController ()<UIAlertViewDelegate, AVCaptureMetadataOutputObjectsDelegate, XYLScanViewDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate>
{
    AVCaptureDevice *frontCamera;  //前置攝像機
    AVCaptureDevice *backCamera;  //後置攝像機
    AVCaptureSession *session;         //捕捉對象
    AVCaptureVideoPreviewLayer *previewLayer;
    AVCaptureInput *input;              //輸入流
    AVCaptureMetadataOutput *output;//輸出流
    BOOL isTorchOn;
}

@property (nonatomic, assign) XYLScaningWarningTone tone;
@property (nonatomic, strong) XYLScanView *overView;    //掃碼界面
@property(strong, nonatomic)XYLBinaryCodeView *binaryCodeView;  //二維碼界面
@property(weak, nonatomic)XYLToolButton *scanButton;
@property(weak, nonatomic)XYLToolButton *payCodeButton;
@property(weak, nonatomic)UILabel *titleLabel;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor blackColor];
    [self scanSelected];
}

    //點擊掃碼
-(void)scanSelected
{
    if (![self.overView isDisplayedInScreen])
    {
#if TARGET_IPHONE_SIMULATOR
    UIAlertController *simulatorAlert = [UIAlertController alertControllerWithTitle:nil message:@"虛擬機不支持相機" preferredStyle:UIAlertControllerStyleActionSheet];
    [simulatorAlert addAction:[UIAlertAction actionWithTitle:@"好吧" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        return;
    }]];
    [self presentViewController:simulatorAlert animated:YES completion:nil];

#elif TARGET_OS_IPHONE
    //判斷相機權限
    [self isVideoUseable];
    self.binaryCodeView.hidden = YES;
    if (self.overView) {
        self.overView.hidden = NO;
    }else{
        //添加掃面界面視圖
        [self initOverView];
        [self initCapture];
        [self config];
        [self initUI];
        [self addGesture];
    }
#endif
    }
}

-(void)isVideoUseable
{
    AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
    if (authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied) 
    {
        UIAlertController *simulatorAlert = [UIAlertController alertControllerWithTitle:nil message:@"相機權限未開通,請打開" preferredStyle:UIAlertControllerStyleActionSheet];
        [simulatorAlert addAction:[UIAlertAction actionWithTitle:@"好吧" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            return;
        }]];
        [self presentViewController:simulatorAlert animated:YES completion:nil];
    }
}
/**
 *  添加掃碼視圖
 */
- (void)initOverView
{
    if (!_overView) {
        _overView = [[XYLScanView alloc]initWithFrame:[UIScreen mainScreen].bounds lineMode:XYLScaningLineModeDeafult ineMoveMode:XYLScaningLineMoveModeUpAndDown];
        _overView.delegate = self;
        [self.view insertSubview:_overView atIndex:1];
    }
}

//設置掃描反饋模式:這裏是聲音提示
- (void)config{
    _tone = XYLScaningWarningToneSound;
}
  • 系統方法捕捉二維碼、條形碼信息
- (void)initCapture
{
    //建立捕捉會話
    session = [[AVCaptureSession alloc]init];
    //高質量採集率
    [session setSessionPreset:AVCaptureSessionPresetHigh];

    //獲取攝像設備
    NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    for (AVCaptureDevice *camera in devices) {
        if (camera.position == AVCaptureDevicePositionFront) {
            frontCamera = camera;
        }else{
            backCamera = camera;
        }
    }
    //建立輸入流
    input = [AVCaptureDeviceInput deviceInputWithDevice:backCamera error:nil];
    
    //輸出流
    output = [[AVCaptureMetadataOutput alloc]init];
    //設置代理 在主線程裏刷新
    [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    
    //添加輸入設備(數據從攝像頭輸入)
    if ([session canAddInput:input]) {
        [session addInput:input];
    }
    //添加輸出數據
    if ([session canAddOutput:output]) {
        [session addOutput:output];
    }
    //設置設置輸入元數據的類型(以下設置條形碼和二維碼兼容)
    output.metadataObjectTypes = @[AVMetadataObjectTypeEAN13Code,
                                   AVMetadataObjectTypeEAN8Code,
                                   AVMetadataObjectTypeCode128Code,
                                   AVMetadataObjectTypeQRCode];

    //添加掃描圖層
    previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:session];
    previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    previewLayer.frame = self.view.layer.bounds;
    [self.view.layer insertSublayer:previewLayer atIndex:0];
    
    //開始捕獲
    [session startRunning];
    
    
    CGFloat screenHeight = ScreenSize.height;
    CGFloat screenWidth = ScreenSize.width;
    CGRect cropRect = CGRectMake((screenWidth - TransparentArea([_overView width], [_overView height]).width) / 2,
                                 (screenHeight - TransparentArea([_overView width], [_overView height]).height) / 2,
                                 TransparentArea([_overView width], [_overView height]).width,
                                 TransparentArea([_overView width], [_overView height]).height);
    //設置掃描區域
    [output setRectOfInterest:CGRectMake(cropRect.origin.y / screenHeight,
                                         cropRect.origin.x / screenWidth,
                                         cropRect.size.height / screenHeight,
                                         cropRect.size.width / screenWidth)];
    
}
  • 獲取結果
/**
 * 獲取掃描數據
 */
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
    NSString *stringValue;
    if (metadataObjects.count > 0) {
        AVMetadataMachineReadableCodeObject *metadateObject = [metadataObjects objectAtIndex:0];
        stringValue = metadateObject.stringValue;
        [self readingFinshedWithMessage:stringValue];
        [previewLayer removeFromSuperlayer];
    }
}

/**
 *  讀取掃描結果
 */
- (void)readingFinshedWithMessage:(NSString *)msg
{
    if (msg) {
        [session stopRunning];
        
        [self playSystemSoundWithStyle:_tone];
        
        [self.overView stopMove];
        
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:msg preferredStyle:UIAlertControllerStyleActionSheet];
        [alert addAction:[UIAlertAction actionWithTitle:@"肯定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            NSLog(@"掃描出來結果%@",msg);
            //todo:在這裏添加掃描結果後的處理
            [self.overView removeFromSuperview];
            self.overView = nil;
            [self payCodeSelected];
        }]];
        [self presentViewController:alert animated:YES completion:nil];
    }else
    {
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:@"讀取失敗" preferredStyle:UIAlertControllerStyleActionSheet];
        [alert addAction:[UIAlertAction actionWithTitle:@"肯定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            NSLog(@"點擊了肯定");
        }]];
        [self presentViewController:alert animated:true completion:nil];
    }
}
  • 掃碼成功聲音提示
/**
 *  展現聲音提示
 */
- (void)playSystemSoundWithStyle:(XYLScaningWarningTone)tone{
    
    NSString *path = [NSString stringWithFormat:@"%@/scan.wav", [[NSBundle mainBundle] resourcePath]];
    SystemSoundID soundID;
    NSURL *filePath = [NSURL fileURLWithPath:path isDirectory:NO];
    AudioServicesCreateSystemSoundID((__bridge CFURLRef)(filePath), &soundID);
    switch (tone) {
        case XYLScaningWarningToneSound:
            AudioServicesPlaySystemSound(soundID);
            break;
        case XYLScaningWarningToneVibrate:
            AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
            break;
        case XYLScaningWarningToneSoundAndVibrate:
            AudioServicesPlaySystemSound(soundID);
            AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
            break;
        default:
            break;
    }
}
  • 說明線程

    你可能看到了,添加掃碼功能的時候,要遵循更多的協議,這是由於這裏使用了AVFoundation框架Apple原生掃描二維碼的一些功能,只須要遵循這些協議就能夠調用裏面的功能了。例如這裏的獲取掃碼結果的方法代理

/**
 * 獲取掃描數據
 */
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection;

而其他的,這裏詳細的註釋就能夠幫助你理解這些代碼了,若是想深刻了解具體實現過程,建議能夠看一下源碼github地址

相關文章
相關標籤/搜索