Swift 二维码扫描 简单实现

3.30看视频  学到了二维码简单的实现 还有一些动画的实现  今天就先记录一下二维码扫描的简单实现  不太好记手写一遍 学习的基础在于模仿嘛

创建一个实现二维码扫描的步骤

1.首先是懒加载创建 会话 输入设备  输出设备

    // 先倒入框架 AVFoundation 
    import AVFoundation
    //通过懒加载 创建输入设备 
    private lazy var deviceInput: AVCaptureDeviceInput? = {
        //获取设备摄像头
        let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
        //使用摄像头为输入设备  创建时需要try一下因为有可能拿不到 摄像头所以返回值有可能为空 该对象为可选(?)类型
        do{
            let input = try AVCaptureDeviceInput(device: device)
            return input
        }catch{
            print(error)
            return nil
        }
    }()
    //创建 会话/输出  比较简单 只需要创建一个对象
    private lazy var session: AVCaptureSession = AVCaptureSession()
    //创建 输出设备
    private lazy var deviceOutput: AVCaptureMetadataOutput = AVCaptureMetadataOutput()
这么第一步 就准备完毕 扫描二维码的 整体就是 输出设备通过 会话来 拿到 输入设备的获取的值 再解析

2.实现扫描二维码  输入输出 添加到会话

        //先判断是否能将 输入输出设备 添加到会话中
        if !session.canAddInput(deviceInput) {
            return
        }
        if !session.canAddOutput(deviceOutput){
            return
        }
        //将设备添加到 会话中
        session.addInput(deviceInput)
        session.addOutput(deviceOutput)

3.设置允许扫描类型

        //设置扫描类型  也就是设置输出设备能够解析的数据类型
          //设置类型时 必须先把设备添加到会话 否则崩溃
        deviceOutput.metadataObjectTypes = deviceOutput.availableMetadataObjectTypes
deviceOutput.availableMetadataObjectTypes 获取到所有的解析类型

4.实现代理 拿到扫描数据

          //设置代理 解析数据   queue线程 
        deviceOutput.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())

5.开始会话

        //开始 执行会话
        session.startRunning()

6.添加图层 实现预览

    //为了更好的操作体验 一般扫描二维码的时候都会加上 预览 和 二维码定位线   
    //还是懒加载 
    private lazy var previewLzyer: AVCaptureVideoPreviewLayer = {
        //预览涂层 想要展示一个界面 界面展示数据  数据通过输入设备获取  会话中则存储了数据
        //注: 闭包 访问外界对象 则需要带上self
        let preview = AVCaptureVideoPreviewLayer(session: self.session)
        preview.frame = UIScreen.mainScreen().bounds
        return preview
    }()
再把预览添加到 二维码界面,但是有可能遮挡到某些空间 则
 view.layer.insertSublayer(<#T##layer: CALayer##CALayer#>, atIndex: <#T##UInt32#>)
插入一个layer视图 在index 第几层

 7.实现代理 绘制预览定位线

   7.1创建一个图层预留使用

    //老样子先懒加载一个使用  创建一个绘制图层 添加到预览视图上毕竟定位框要在预览视图上定位
    private lazy var drawingLayer: CALayer = {
       let draw = CALayer()
        draw.frame = UIScreen.mainScreen().bounds
        return draw
    }()

  7.2 实现代理方法   第四步中已经说了遵守了那个协议

extension ScanCodeController: AVCaptureMetadataOutputObjectsDelegate{
    
    func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!
, fromConnection connection: AVCaptureConnection!){ //试着输出一下咱们获取到的数据 这里只是展示一下这个方法的用处 print(metadataObjects.last) //获取二维码内容 这个是咱们需要的 url 先存起来 var str = metadataObjects.last?.stringValue; }

  7.3要绘制一个图形咱们必须要从 其中获取到二维码的4个点    接下来的操作还是在上面那个协议方法中

        //获取二维码位置 前面的打印中咱们就看的出其中的一些数据 是看不懂的 所以要转换一下
        //转换坐标  先便利一下其中的内容
        for objec in metadataObjects{
//判断数据是否为机器是识别类型 if objec is AVMetadataMachineReadableCodeObject{
//转换类型 将坐标系转换为界面可识别坐标 //转换AVMetadataObject's类型 转换为 预览层的坐标
let codeObject = previewLzyer.transformedMetadataObjectForMetadataObject(objec as! AVMetadataObject) as!
AVMetadataMachineReadableCodeObject // print(codeObject) 试着输出一下咱们转换出的的东西 //绘制图形 Drawing(codeObject) } }

  7.4接下来咱们就该绘制图形 并且添加到视图中  代码有点多写了一个方法Drawing(codeObject)

 

    /*绘制图形方法
       codeObject 存储二维码位置
    */
    private func Drawing(codeObject:AVMetadataMachineReadableCodeObject){
//判断 如果没有值就不必要执行了
if codeObject.corners.isEmpty{ return } var index:Int = 0 //标记 let count:Int = codeObject.corners.count //数组corners中的个数 用于取值 //1.创建图层 let layer = CAShapeLayer() //2.设置图层属性 layer.borderWidth = 4 //边框宽度 layer.strokeColor = UIColor.greenColor().CGColor //边框颜色 layer.fillColor = UIColor.clearColor().CGColor //框内内部颜色 //3.设置路径 //创建一个 存储的 点 和 路径 let path = UIBezierPath() var point = CGPointZero //是一个 二维码四点 的数组 print(codeObject.corners) //打印出来一看就明白 //移动到第一个点 CGPointMakeWithDictionaryRepresentation((codeObject.corners[index++] as! CFDictionaryRef), &point) path.moveToPoint(point) //循环取出其中的字典 转换成 点 放到path中 while index < count { //从字典中拿出 点 CGPointMakeWithDictionaryRepresentation((codeObject.corners[index++] as! CFDictionaryRef), &point) path.addLineToPoint(point) } //关闭路径 path.closePath() //绘制路径 layer.path = path.CGPath //4.图层添加到drawingLayer上 drawingLayer.addSublayer(layer) }

 

  7.5 清空绘图,否则会预览视图上会有多个定位框  放到绘图方法开始就行

 

 

    //清空drawingLayer
    private func clearDrawing() {
        //先判断其中是否有绘图
        if drawingLayer.sublayers?.count == 0 || drawingLayer.sublayers == nil
        {
            return
        }
        
        //清空子控件
        for layerdraw in drawingLayer.sublayers!
        {
            layerdraw.removeFromSuperlayer()
        }
    }

 

转载于:https://www.cnblogs.com/GGBigBong/p/5340134.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值