• 二维码生成与扫描


    偶尔用这一块的东西,总是记不住,所以写了两个demo 注释写的非常详细.

    二维码的生成:

    #import "ViewController.h"
    #import <CoreImage/CoreImage.h>
    
    @interface ViewController ()
    
    @property (weak, nonatomic) IBOutlet UIImageView *codeImage;
    
    @end
    
    
    /*
     1. 生成二维码 要导入CoreImage 这个系统原生框架 (因为要去获取内置滤镜 支持各种种类的二维码)
     
     2.
     (
     inputMessage,  链接的字符串  (输入的 就是咱们自己去设定的)
     inputCorrectionLevel   链接类型
     )
    
     3. 要记住 扫二维码 是一个操作 根据得到的这个字符串的类型 去让他去做下一步的操作.
     
     4.filter.outputImage 得到图片
     
     5.调整清晰度
     
     
     */
    @implementation ViewController
    
    - (void)viewDidLoad {
        
        [super viewDidLoad];
      
        // 1. 创建滤镜对象  内置滤镜 支持各种种类的二维码 跟一个类型 具体什么格式 不清楚
          // 通过一个分类的属性 来进行打印 打印所有的对象
       // NSLog(@"%@",[CIFilter filterNamesInCategory:kCICategoryBuiltIn]);
          // 二维码滤镜已经获取
        CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
        
        // 2. 设置默认值
        [filter setDefaults];
        
        // 3.输入字符串
        NSLog(@"%@",filter.inputKeys);  // 完全可以吧这个字符串去看做是一个特殊的字符串类型
        
        // 只读属性 利用KVC 进行复制
        // CIQRCodeGenerator filter requires NSData for inputMessage 这个哥们必须是一个二维码
        // 将字符串 转换成2进制的方法
        [filter setValue:[@"http://mp.weixin.qq.com/wiki/14/9f9c82c1af308e3b14ba9b973f99a8ba.html" dataUsingEncoding:NSUTF8StringEncoding]
                  forKey:@"inputMessage"];
        
         NSLog(@"%@",filter.inputKeys);
        
        // 5.放大图片 CIImage 是继承自NSObject (原因:CIImage 确实是放大了五倍,然后CodeImageFrame没有改变,像素点密集 变得清晰)
        CIImage *resultImage = [filter.outputImage imageByApplyingTransform:CGAffineTransformMakeScale(5, 5)];
        self.codeImage.image = [UIImage imageWithCIImage:resultImage];
        
    //    // 4.获取二维码的图片
    //    CIImage *imageC = filter.outputImage;
    //    
    //    self.codeImage.image = [UIImage imageWithCIImage:imageC];
    //    
    }
    
    @end

    二维码的读取:

    #import "ViewController.h"
    #import <AVFoundation/AVFoundation.h>
    
    @interface ViewController ()<AVCaptureMetadataOutputObjectsDelegate>
    
    @property (nonatomic,strong)AVCaptureSession *session;
    
    @property (nonatomic,strong)AVCaptureDeviceInput *input;
    
    @property (nonatomic,strong)AVCaptureMetadataOutput *output;
    
    // 创建预览视图  layer层 专门用来显示输入设备来捕捉到的画面
    @property (nonatomic,strong)AVCaptureVideoPreviewLayer *viewLayer; // 继承自CALayer
    
    @end
    
    /*
     1.导入AVFoundtation 框架
     
     输入设备 相机  麦克 键盘等   AVCaptureDeviceInput(子类)    AVCaptureInput(父类)
    
     输出设备  解析  (元数据) AVCaptureMetadataOutput -> AVCaptureOutput
     
     会话链接  将输入设备和输出设备去建立联系
     
     二维码的扫码和屏幕显示的东西都是没有关系的,只是和摄像头对准的二维码有关 至于后来的页面跳转和别的操作 就是其他的业务逻辑 咱们只是拿到数据之后 对这个字符串去进行分析 格式
     
     元数据: 元数据(MetaData)
         因为它们是用来描述具体数据/信息的数据/信息。
         在日常生活中,元数据无所不在。有一类事物,就可以定义一套元数据。
         元数据最大的好处是,它使信息的描述和分类可以实现格式化,从而为机器处理创造了可能。
     
     1. 创建输入设备对象 AVCaptureDeviceInput 并且设置好设备类型
     
     2,创建输出设备对象 AVCaptureMetadataOutput (元数据对象)
     
     3. 创建 AVCaptureSession 对象 将输入输出(添加)建立联系
     
     4. 设置视频范围   [self.session setSessionPreset:AVCaptureSessionPresetHigh];
     
     5.开启
     
     6,设置 AVCaptureMetadataOutput 的数据 并获取对象.. (
     
     7. 设置输出设备的类型 (注意 有坑)
     
     
     */
    
    /*
     输出设备的与数据得到可用参数
     (
     "org.iso.Aztec",
     "org.iso.Code128",
     "org.iso.Code39",
     "org.iso.Code39Mod43",
     "com.intermec.Code93",
     "org.iso.DataMatrix",
     "org.gs1.EAN-13",
     "org.gs1.EAN-8",
     "org.ansi.Interleaved2of5",
     "org.gs1.ITF14",
     "org.iso.PDF417",
     "org.iso.QRCode",    二维码 类型
     "org.gs1.UPC-E",
     face
     )
     */
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        
        [super viewDidLoad];
    }
    
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        
        // 1 创建输入设备 (类型为相机)
         // 给定一个设备 让咱们知道是哪个设备 AVMediaTypeVideo  就是这个样式的的字符串 ??
        // 元数据
        AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        self.input  = [[AVCaptureDeviceInput alloc]initWithDevice:device error:nil];
        
        
        // 2, 创建输出设备  用来去解析
        self.output = [[AVCaptureMetadataOutput alloc]init]; // ??
        // 2,1 设置输出设备的代理  (这个地方的代理设置的地放比较特殊) // 这个地方为什么要去设置一个全局队列
        [ self.output setMetadataObjectsDelegate:self queue:dispatch_get_global_queue(0, 0)];
        
        
    //    //6. 设置元数据类型区别的
    //    // 先去打印一下可用类型有哪些 (7.0 之前 和7.0 之后  这个地方是有)
    //    NSLog(@"%@",self.output.metadataObjectTypes); // 元数据可以利用的数据类型
    //    
        
        // 3. 创建会话层  建立联系
        
        self.session  =  [[AVCaptureSession alloc]init];
        
        // 3.1 先判断能否添加 设备  然后添加
        
        if ([self.session canAddInput:self.input]) {
            
            [self.session addInput:self.input];
        }
        if ([self.session canAddOutput:self.output]) {
            [self.session  addOutput:self.output];
        }
        
        // 5, 设置视频范围
        //[self.session setSessionPreset:AVCaptureSessionPresetHigh];
        // high  是自适应的
        [self.session setSessionPreset:AVCaptureSessionPresetHigh];
        
        
        //6. 设置元数据类型
        // 先去打印一下可用类型有哪些
        NSLog(@"%@",self.output.availableMetadataObjectTypes); // 元数据可以利用的数据类型
         // 根据类型去进行设置
        [self.output setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]];
       
         // 4. 开启会话
        [self.session startRunning];
        
        // 8. 增加一个预览视图 用来去显示输入设备的画面
           // 创建
        self.viewLayer = [[AVCaptureVideoPreviewLayer alloc]initWithSession:self.session];
          // 设置frame
        self.viewLayer.frame = self.view.bounds;
       // [self.view addSubview:self.viewLayer];   继承自CALayer
        [self.view.layer addSublayer:self.viewLayer];
        
    }
    
    #pragma mark -- 代理的方法 解析数据的时候就会去调用这个方法
    // 数据解析完成之后 会给你返回一个字符串
    - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{
        // 扫描的数据全部都放在 metadataObjects 既然是数组 那么久先去打印他
        //NSLog(@"%@",metadataObjects);
        //取出扫描的数据
        AVMetadataMachineReadableCodeObject *objc = [metadataObjects firstObject];
        NSLog(@"%@",objc.stringValue);
        // 关闭会话
        [self.session stopRunning];
        // 移除这个层
        [self.viewLayer removeFromSuperlayer];
    }
    
    
    @end
  • 相关阅读:
    [PHP] 适配器模式的日常使用
    [MySQL] timestamp和datetime的区别和大坑
    [PHP] foreach循环的引用赋值可能导致的问题
    [PHP] 邮件发送mail()函数失败问题 sendmail命令与postfix
    [日常] 腾讯云发送邮件失败问题
    [日常] 正则表达式 小括号() 中括号[] 大括号{}
    [Linux] awk与posix字符集
    [PHP] 工厂模式的日常使用
    [PHP] 抽象类abstract的回顾
    [日常]灵活的频率限制实现
  • 原文地址:https://www.cnblogs.com/zhubaofeng/p/5433316.html
Copyright © 2020-2023  润新知