iOS 开发 二维码扫描详解

本文详细介绍了如何在iOS开发中实现二维码扫描功能,包括自定义扫描控制器的.m代码,以及如何创建和使用预览图层进行二维码检测。通过实例演示了整个过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.扫描二维码的控制器.m代码

#import "JDGScanQRcodeController.h"
#import <AVFoundation/AVFoundation.h>
#import <SafariServices/SafariServices.h>
#import "JDGScanQRcodeView.h"

@interface JDGScanQRcodeController ()<AVCaptureMetadataOutputObjectsDelegate>
// 1.输入设备(采集信息)  摄像头  键盘   麦克风
@property (nonatomic, strong) AVCaptureDeviceInput *deviceInput;
// 2.输出设备(解析数据)  Metadata:元数据
@property (nonatomic, strong) AVCaptureMetadataOutput *metadataOutput;
// 3.会话 (连接输入和输出设备)
@property (nonatomic, strong) AVCaptureSession *session;
// 4.预览的图层
@property (nonatomic, strong) AVCaptureVideoPreviewLayer *previewLayer;

@property (nonatomic, weak) JDGScanQRcodeView *scanQRcodeView;
@end

@implementation JDGScanQRcodeController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.navigationItem.title = @"扫描二维码";
    
    [self setUpUI];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    // 控制器即将出先的时候开启会发,进行扫描
    [self.session startRunning];
}

- (void)setUpUI {
    // 二维码本质就是一个字符串
    
    // 1.输入设备(采集信息)  摄像头  键盘   麦克风
    // 默认就是后置摄像头
    AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    self.deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:nil];
    // 2.输出设备(解析数据)
    self.metadataOutput = [[AVCaptureMetadataOutput alloc] init];
    // 设置代理
    [self.metadataOutput setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    // 3.会话 (连接输入和输出设备)
    self.session = [[AVCaptureSession alloc] init];
    if ([self.session canAddInput:self.deviceInput]) {
        [self.session addInput:self.deviceInput];
    }
    if ([self.session canAddOutput:self.metadataOutput]) {
        [self.session addOutput:self.metadataOutput];
    }
    // 设置解析的类型  不要写在会话之前 会崩溃
    self.metadataOutput.metadataObjectTypes = @[AVMetadataObjectTypeQRCode];
    //   预览图层的主要功能就是将摄像头采集的数据及时的传输到预览图层,使得用户可以在预览图层实时的看到画面,主要类是AVCapturePreviewLayer,创建起来也非常容易
    //自定义扫描视图
    JDGScanQRcodeView *scanQRcodeView = [[JDGScanQRcodeView alloc] initWithFrame:self.view.bounds];
    self.scanQRcodeView = scanQRcodeView;
    scanQRcodeView.session = self.session;
    [self.view addSubview:scanQRcodeView];
    
    // 5.开启会话
    [self.session startRunning];

}

// 实现AVCaptureMetadataOutputObjectsDelegate
// 解析到二维码数据后调用
// metadataObjects:解析到的信息
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
    // 关闭会话
    [self.session stopRunning];
    // 不能移除layer,移除后返回什么东西都没有了
//    [self.scanQRcodeView removeFromSuperview];
    for (AVMetadataMachineReadableCodeObject * objc in metadataObjects) {
        NSLog(@"%@",objc.stringValue);

		// 类似于Safari浏览器加载扫描出来的URLString进行加载页面
        SFSafariViewController *safariVC = [[SFSafariViewController alloc] initWithURL:[NSURL URLWithString:objc.stringValue]];
        [self presentViewController:safariVC animated:YES completion:nil];
        
    }
}

自定义预览图层

#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>

@interface JDGScanQRcodeView : UIView
// session
@property (nonatomic, strong) AVCaptureSession *session;

@end
#import "JDGScanQRcodeView.h"
#import "Masonry.h"

@interface JDGScanQRcodeView ()
// 图框
@property (nonatomic, strong) UIImageView *imageView;
// 扫描线
@property (nonatomic, strong) UIImageView *lineImageView;
// 定时器开启扫描线来回移动
@property (nonatomic, strong) NSTimer *timer;
@end

@implementation JDGScanQRcodeView

- (void)setSession:(AVCaptureSession *)session {
    _session = session;
    // 预览图层
    AVCaptureVideoPreviewLayer *layer = (AVCaptureVideoPreviewLayer *)self.layer;
    layer.session = session;
}

// 初始化预览图层
+ (Class)layerClass {
    return [AVCaptureVideoPreviewLayer class];
}

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        [self initUiConfig];
    }
    return self;
}

//在一个视图中设置二维码UI的垃圾代码
- (void)initUiConfig {
    //设置背景图片
    self.imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"myCenter_pick_bg.png"]];
    //设置位置到界面的中间
    self.imageView.frame = CGRectMake(self.bounds.size.width * 0.5 - 140, self.bounds.size.height * 0.5 - 140, 280, 280);

    //添加到视图上
    [self addSubview:self.imageView];
    
    //初始化二维码的扫描线的位置
    self.lineImageView = [[UIImageView alloc] initWithFrame:CGRectMake(30, 10, 220, 2)];
    self.lineImageView.image = [UIImage imageNamed:@"myCenter_line.png"];
    [self.imageView addSubview:self.lineImageView];
    
    UILabel *tipLabel = [[UILabel alloc] init];
    tipLabel.text = @"将二维码放入框内,即可自动扫描";
    tipLabel.font = [UIFont systemFontOfSize:14.0];
    tipLabel.textColor = [UIColor whiteColor];
    [self addSubview:tipLabel];
    
    [tipLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.mas_equalTo(self.imageView.mas_bottom).offset(10);
        make.centerX.mas_equalTo(self.mas_centerX);
    }];
    
    //开启定时器
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(animation) userInfo:nil repeats:YES];
}


// 扫描线动态扫描
- (void)animation {
    [UIView animateWithDuration:1 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
        self.lineImageView.frame = CGRectMake(30, 260, 220, 2);
    } completion:^(BOOL finished) {
        self.lineImageView.frame = CGRectMake(30, 10, 220, 2);
    }];
}

@end

实例

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值