Swift 二维码扫码页面

15 篇文章 1 订阅
该博客主要介绍了如何在iOS应用中实现二维码扫描功能。通过ScanController.swift代码展示了创建扫描界面,设置扫描区域,捕获并解析二维码的过程。此外,还提到了如何将扫描结果通过闭包回调到调用页面,并提供了详细的界面布局代码,包括边框和扫描框的绘制。
摘要由CSDN通过智能技术生成

调用扫描二维码界面,如图

二维码扫描界面代码 ScanController.swift

//
//  ScanController.swift
//  GaoPei
//
//  Created by iscopy on 2020/6/16.
//  Copyright © 2020 . All rights reserved.
//

import UIKit
import AVFoundation
//重命名一个闭包
typealias sendScan = (_ string : String,_ type : String) -> Void
class ScanController: UIViewController, AVCaptureMetadataOutputObjectsDelegate {

    var session:AVCaptureSession!
    var screenWidth : CGFloat!
    var screenHeight:CGFloat!
    
    //创建一个闭包属性
    var sendScans : sendScan?
    //属性传值
    var type : String? = nil
        
    override func viewDidLoad() {
        super.viewDidLoad()
        screenWidth = self.view.bounds.width
        screenHeight = self.view.bounds.height
        setView()
        setCamera()
    }
    //设置除了扫描区以外的视图
    //半径
    let radius:Float = 150
    //偏移
    let deviation:Float = 50
    //边框
    let frames:Float = 3
    //边框长度
    let frameLong:Float = 10
    func setView(){
        let topTime = UIView(frame: CGRect(x: 0, y: 0, width: screenWidth, height: 20))
        topTime.backgroundColor = UIColor.white
        self.view.addSubview(topTime)
        
        //框框
        let colorOuterFrame:UIColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.6)
        let leftView = UIView(frame: CGRect(x: 0, y: 20, width: screenWidth/2-CGFloat(self.radius), height: screenHeight))
        leftView.backgroundColor = colorOuterFrame
        self.view.addSubview(leftView)
        let rightView = UIView(frame: CGRect(x: screenWidth/2+CGFloat(self.radius), y: 20, width: screenWidth/2-CGFloat(self.radius), height: screenHeight))
        rightView.backgroundColor = colorOuterFrame
        self.view.addSubview(rightView)
        let topView = UIView(frame: CGRect(x: screenWidth/2-CGFloat(self.radius), y: 20, width: CGFloat(self.radius)*2, height: screenHeight/2 - CGFloat(self.radius) - CGFloat(self.deviation) - 20))
        topView.backgroundColor = colorOuterFrame
        self.view.addSubview(topView)
        let bottomView = UIView(frame: CGRect(x: screenWidth/2-CGFloat(self.radius), y: screenHeight/2 + CGFloat(self.radius) - CGFloat(self.deviation), width: CGFloat(self.radius)*2, height: screenHeight/2-CGFloat(self.radius) + CGFloat(self.deviation)))
        bottomView.backgroundColor = colorOuterFrame
        self.view.addSubview(bottomView)
        
        
        //边框
        let colorFrame:UIColor = UIColor(red: 240, green: 248, blue: 255, alpha: 1)
        //左上
        let leftTopLeftx = screenWidth/2 - CGFloat(self.radius)
        let leftTopLefty = screenHeight/2 - CGFloat(self.radius) - CGFloat(self.deviation) - CGFloat(self.frames)
        let leftTopLeft = UIView(frame: CGRect(x: leftTopLeftx, y: leftTopLefty, width:  CGFloat(self.frameLong) - CGFloat(self.frames), height:  CGFloat(self.frames)))
        leftTopLeft.backgroundColor = colorFrame
        self.view.addSubview(leftTopLeft)
        let leftTopTopx = screenWidth/2 - CGFloat(self.radius) - CGFloat(self.frames)
        let leftTopTopy = screenHeight/2 - CGFloat(self.radius) - CGFloat(self.deviation) - CGFloat(self.frames)
        let leftTopTop = UIView(frame: CGRect(x: leftTopTopx, y: leftTopTopy, width:  CGFloat(self.frames), height:  CGFloat(self.frameLong)))
        leftTopTop.backgroundColor = colorFrame
        self.view.addSubview(leftTopTop)
        //右上
        let rightTopRightx = screenWidth/2 + CGFloat(self.radius)
        let rightTopRighty = screenHeight/2 - CGFloat(self.radius) - CGFloat(self.deviation)
        let rightTopRight = UIView(frame: CGRect(x: rightTopRightx, y: rightTopRighty, width:   CGFloat(self.frames), height:  CGFloat(self.frameLong) - CGFloat(self.frames)))
        rightTopRight.backgroundColor = colorFrame
        self.view.addSubview(rightTopRight)
        let rightTopTopx = screenWidth/2 + CGFloat(self.radius) - CGFloat(self.frameLong) + CGFloat(self.frames)
        let rightTopTopy = screenHeight/2 - CGFloat(self.radius) - CGFloat(self.deviation) - CGFloat(self.frames)
        let rightTopTop = UIView(frame: CGRect(
            x: rightTopTopx,
            y: rightTopTopy,
            width:  CGFloat(self.frameLong),
            height:  CGFloat(self.frames)))
        rightTopTop.backgroundColor = colorFrame
        self.view.addSubview(rightTopTop)
        //左下
        let leftBottomLeftx = screenWidth/2 - CGFloat(self.radius) - CGFloat(self.frames)
        let leftBottomLefty1 = screenHeight/2 + CGFloat(self.radius) - CGFloat(self.deviation)
        let leftBottomLefty = leftBottomLefty1 + CGFloat(self.frames) - CGFloat(self.frameLong)
        let leftBottomLeft = UIView(frame: CGRect(x: leftBottomLeftx, y: leftBottomLefty, width:  CGFloat(self.frames), height:  CGFloat(self.frameLong)))
        leftBottomLeft.backgroundColor = colorFrame
        self.view.addSubview(leftBottomLeft)
        let leftBottomBottomx = screenWidth/2 - CGFloat(self.radius)
        let leftBottomBottomy = screenHeight/2 + CGFloat(self.radius) - CGFloat(self.deviation)
        let leftBottomBottom = UIView(frame: CGRect(x: leftBottomBottomx, y: leftBottomBottomy, width:  CGFloat(self.frameLong) - CGFloat(self.frames), height:  CGFloat(self.frames)))
        leftBottomBottom.backgroundColor = colorFrame
        self.view.addSubview(leftBottomBottom)
        //右下
        let rightBottomRightx = screenWidth/2 + CGFloat(self.radius)
        let rightBottomRighty1 = screenHeight/2 + CGFloat(self.radius)
        let rightBottomRighty = rightBottomRighty1 - CGFloat(self.deviation) - CGFloat(self.frameLong) + CGFloat(self.frames)
        let rightBottomRight = UIView(frame: CGRect(x: rightBottomRightx, y: rightBottomRighty, width:  CGFloat(self.frames), height:  CGFloat(self.frameLong)))
        rightBottomRight.backgroundColor = colorFrame
        self.view.addSubview(rightBottomRight)
        let rightBottomBottomx = screenWidth/2 + CGFloat(self.radius) - CGFloat(self.frameLong) + CGFloat(self.frames)
        let rightBottomBottomy = screenHeight/2 + CGFloat(self.radius) - CGFloat(self.deviation)
        let rightBottomBottom = UIView(frame: CGRect(x: rightBottomBottomx, y: rightBottomBottomy, width:  CGFloat(self.frameLong) - CGFloat(self.frames), height:  CGFloat(self.frames)))
        rightBottomBottom.backgroundColor = colorFrame
        self.view.addSubview(rightBottomBottom)
        
        // button  点击无参数
        let button = UIButton(frame: CGRect(x: 20, y: 50, width: 50, height: 30))
        button.backgroundColor = UIColor.blue
        button.setTitle("返回", for: UIControl.State.normal)
        button.addTarget(self, action: #selector(ScanController.buttonTap), for: UIControl.Event.touchUpInside)
        self.view.addSubview(button)
    }
    
    //selector 其实是 Objective-C runtime 的概念
    @objc func buttonTap() {
        print("buttonTap")
        //self.navigationController?.popViewController(animated: true)
        self.dismiss(animated: true, completion:nil)
    }

    //设置相机
    func setCamera(){

    //获取摄像设备
    guard let device = AVCaptureDevice.default(for: AVMediaType.video) else {
        return
    }

    do {
        //创建输入流
        let input =  try AVCaptureDeviceInput(device: device)
        //创建输出流
        let output = AVCaptureMetadataOutput()
        //设置会话
        session = AVCaptureSession()
        //连接输入输出
        if session.canAddInput(input){
            session.addInput(input)
        }

        if session.canAddOutput(output){
            session.addOutput(output)
            //设置输出流代理,从接收端收到的所有元数据都会被传送到delegate方法,所有delegate方法均在queue中执行
            output.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
            //设置扫描二维码类型
            output.metadataObjectTypes = [ AVMetadataObject.ObjectType.qr,AVMetadataObject.ObjectType.ean13,
                        AVMetadataObject.ObjectType.ean8, AVMetadataObject.ObjectType.code128,
                        AVMetadataObject.ObjectType.code39,AVMetadataObject.ObjectType.code93]
            //扫描区域
            //rectOfInterest 属性中x和y互换,width和height互换。
            //output.rectOfInterest = CGRect(x: CGFloat(self.radius)/screenHeight, y: (screenWidth/2-CGFloat(self.radius))/screenWidth, width: (CGFloat(self.radius) + CGFloat(self.deviation))/screenHeight, height: (CGFloat(self.radius) + CGFloat(self.deviation))/screenWidth)
            output.rectOfInterest = CGRect(
                x: (screenHeight/2 - CGFloat(self.radius) - CGFloat(self.deviation))/screenHeight,
                y: (screenWidth/2 - CGFloat(self.radius))/screenWidth,
                width: CGFloat(self.radius)*2/screenHeight,
                height: CGFloat(self.radius)*2/screenWidth)
            }
            //捕捉图层
            let previewLayer = AVCaptureVideoPreviewLayer(session: session)
            previewLayer.videoGravity = .resizeAspectFill
            previewLayer.frame = self.view.layer.bounds
            self.view.layer.insertSublayer(previewLayer, at: 0)
            //持续对焦
            if device.isFocusModeSupported(.continuousAutoFocus){
                try  input.device.lockForConfiguration()
                input.device.focusMode = .continuousAutoFocus
                input.device.unlockForConfiguration()
            }
            session.startRunning()
            } catch  {
            }
        }

    //扫描完成的代理
    func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
        session?.stopRunning()
        if let metadataObject = metadataObjects.first {
            let readableObject = metadataObject as! AVMetadataMachineReadableCodeObject
            let str = readableObject.stringValue!
            
            //self.navigationController?.popViewController(animated: true)
            self.dismiss(animated: true, completion:nil)
            //将值附在闭包上,传到First页面
            self.sendScans!(self.intercepts(str), type ?? "0000")
        }
    }
    
    //MARK:- 截取
    func intercepts(_ code:String) -> String {
        var codes = code
        if codes.contains("http"){
            if codes.contains("code="){
                let jie = codes.count - Strings.positionOf(code: codes, sub: "code=", backwards:true) - 5
                codes = String(codes.suffix(jie))
            }else if codes.contains("c="){
                let jie = codes.count - Strings.positionOf(code: codes, sub: "c=", backwards:true) - 2
                codes = String(codes.suffix(jie))
            }else{
                if codes.contains("c?"){
                    let jie = codes.count - Strings.positionOf(code: codes, sub: "c?", backwards:true) - 2
                    codes = String(codes.suffix(jie))
                }
            }
        }
        return codes
    }

}

调用 ScanController.swift 获取扫码数据

        let scan = ScanController()
        //将传过来的值  赋给label
        scan.sendScans = { (strings : String, type : String) -> Void in
            //print("\(strings)\(type)")
            self.listDataAdd(code: strings)
        }
        scan.type = "scan"
        scan.modalPresentationStyle = .fullScreen
        self.present(scan, animated: true, completion: nil)

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值