当前位置: 首页 > news >正文

iOS_从相机或相册里扫描二维码或条形码

文章目录

    • 1. 从相机里扫描
      • 1.1 申请相机权限
      • 1.2 创建Scanner
      • 1.3 开始扫描
      • 1.4 处理扫描结果
    • 2. 从相册里扫描
      • 2.1 获取相册权限
      • 2.2 打开相册
      • 2.3 获得选择结果
      • 2.4 解析相片中的二维码或条形码


1. 从相机里扫描

1.1 申请相机权限

  • 导入: import AVFoundation
  • 在项目的 Info.plist 文件里添加 Privacy - Camera Usage Descriptio 描述申请使用相机权限。
  • 查询相机权限: AVCaptureDevice.authorizationStatus(for: .video)
  • 权限类型:AVAuthorizationStatus
notDetermined   未申请
restricted      受限制
denied          已拒绝
authorized      已授权
  • 请求相机权限,系统弹出授权申请提示:
AVCaptureDevice.requestAccess(for: .video) { (status) in// handle request result
}

1.2 创建Scanner

  • 获得设备:
 guard let device = AVCaptureDevice.default(for: .video) else {print("device error")return
}
  • 创建input:
 let input: AVCaptureDeviceInput
do {input = try AVCaptureDeviceInput(device: device)
} catch {print("input error")return
}
if self.captureSession.canAddInput(input) {self.captureSession.addInput(input)
} else {print("session can't add input")return
}
  • 创建 output:
let output = AVCaptureMetadataOutput()
if self.captureSession.canAddOutput(output) {// Tips: add output must before of set outputself.captureSession.addOutput(output)
} else {print("session can't add output")return
}// Set metadata identification type qr: QR code; Other: Barcode
// 设置扫描类型(qr:二维码,其他:条形码)
let hopeSupportTypes = [AVMetadataObject.ObjectType.qr,AVMetadataObject.ObjectType.ean13,AVMetadataObject.ObjectType.ean8,AVMetadataObject.ObjectType.pdf417]
var types: [AVMetadataObject.ObjectType] = []
for type in hopeSupportTypes {if output.availableMetadataObjectTypes.contains(type) {types.append(type)}
}
output.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
output.metadataObjectTypes = types        
output.rectOfInterest = CGRect(x: 0, y: 0,width: self.view.bounds.size.width,height: self.view.bounds.size.height)
  • 设置预览视图:
let previewLayer = AVCaptureVideoPreviewLayer(session: self.captureSession)
previewLayer.frame = scanView.layer.bounds
previewLayer.videoGravity = .resizeAspectFill
scanView.layer.addSublayer(previewLayer)

1.3 开始扫描

Tips: 不能在主线程中扫描,否则会无法响应用户操作,导致卡死现象

DispatchQueue.global(qos: .userInitiated).async {self.captureSession.startRunning()
}

1.4 处理扫描结果

遵循 AVCaptureMetadataOutputObjectsDelegate 协议,实现扫描回调方法:

 func metadataOutput(_ output: AVCaptureMetadataOutput,didOutput metadataObjects: [AVMetadataObject],from connection: AVCaptureConnection) {guard let metadataObject = metadataObjects.first else {captureSession.stopRunning()return}guard let readableObject = metadataObject as? AVMetadataMachineReadableCodeObject else {print("as? AVMetadataMachineReadableCodeObject faliue")return}guard let stringValue = readableObject.stringValue else {print("stringValue faliue")return}AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))print("scan result: \(stringValue)")   // print resultcaptureSession.stopRunning()
}

2. 从相册里扫描

2.1 获取相册权限

  • 导入: import Photos
  • 在项目的 Info.plist 文件里添加 Privacy - Photo Library Usage Description 描述申请访问相册权限。
  • 查询相机权限:PHPhotoLibrary.authorizationStatus()
  • 权限类型:PHAuthorizationStatus
notDetermined   未申请
restricted      受限制
denied          已拒绝
authorized      已授权
limited         已授权有限库访问
  • 请求相册权限,系统弹出授权申请提示:
PHPhotoLibrary.requestAuthorization { (status) in// handle request result
}

2.2 打开相册

Tips: 打开相册必须在主线程中执行

 /// have photos permission
DispatchQueue.main.async {self.openPhotoLabrary()
}private func openPhotoLabrary() {let picker = UIImagePickerController()picker.title = "Photos"picker.delegate = selfpicker.allowsEditing = truepicker.sourceType = .photoLibrarypicker.navigationBar.barStyle = .defaultself.present(picker, animated: true, completion: nil)
}

2.3 获得选择结果

遵循 UIImagePickerControllerDelegateUINavigationControllerDelegate 协议,并实现选中相片后触发的协议方法:

func imagePickerController(_ picker: UIImagePickerController,didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {dismiss(animated: true)guard let image = info[.originalImage] as? UIImage else {print("choose not image")return}parseBarCode(image: image)
}

2.4 解析相片中的二维码或条形码

导入:import Vision

 /// parse qrCode or barCode
private func parseBarCode(image: UIImage) {guard let cgimg = image.cgImage else {return}let request = VNDetectBarcodesRequest { req, err inif let error = err {print("parseBarCode error: \(error)")return}self.handleResults(req.results)}let handler = VNImageRequestHandler(cgImage: cgimg)do {try handler.perform([request])} catch {print("parseBarCode error: \(error)")}
}private func handleResults(_ result: [VNObservation]?) {guard let results = result, results.count > 0 else {print("parseBarCode result is nil: \(String(describing: result))")return}for result in results {self.handleResult(result)}
}private func handleResult(_ result: VNObservation) {guard let barcode = result as? VNBarcodeObservation,let value = barcode.payloadStringValue else {print("handleResult covert to string error: \(result)")return}if barcode.symbology == .qr {print("二维码: \(value)")} else {print("条形码: \(value), \(barcode.symbology.rawValue)")}
}

github demo


参考:
iOS16 Swift二维码/条形码扫描+相册获取识别

相关文章:

iOS_从相机或相册里扫描二维码或条形码

文章目录1. 从相机里扫描1.1 申请相机权限1.2 创建Scanner1.3 开始扫描1.4 处理扫描结果2. 从相册里扫描2.1 获取相册权限2.2 打开相册2.3 获得选择结果2.4 解析相片中的二维码或条形码1. 从相机里扫描 1.1 申请相机权限 导入: import AVFoundation在项目的 Info.…...

Python 自动化指南(繁琐工作自动化)第二版:十六、使用 CSV 文件和 JSON 数据

原文:https://automatetheboringstuff.com/2e/chapter16/ 在第 15 章,你学习了如何从 PDF 和 Word 文档中提取文本。这些文件是二进制格式的,需要特殊的 Python 模块来访问它们的数据。另一方面,CSV 和 JSON 文件只是纯文本文件。…...

knife4j接口文档

knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案,前身是swagger-bootstrap-ui,取名knife4j是希望它能像一把匕首一样小巧,轻量,并且功能强悍!其底层是对Springfox的封装,使用方式也和Springfox一致,只是对接口文档UI进行了优化。 核心功能…...

Windows机器安装SSH搭建,自己搞个局域网机房玩一玩

Windows机器安装SSH搭建为啥要装SSH安装OpenSSH使用 Windows 设置来安装 OpenSSHps脚本在线安装ps脚本离线安装其他二进制安装包安装为啥要装SSH 家里有多台Win机器,一台主机两个笔记本,本着不浪费的原则,打算把它们在平时的工作学习中利用起…...

二叉树的前序遍历(力扣144)

目录 题目描述: 解法一:递归法 解法二:迭代法 解法三:Morris 遍历 二叉树的前序遍历 题目描述: 给你二叉树的根节点 root ,返回它节点值的 前序 遍历。 示例 1: 输入:root […...

【数据库管理】①实例与数据库

1.Oracle RDBMS 架构图 2. Oracle 体系结构 由此区分database和instance的区别 No.1.oracle serverdatabase instance2.databasedata file、control file、redo log file3.instancean instance accesses a database4.oracle memorySGA PGA(oracle的内存结构)5.instanceSGA …...

vba:单元格的选择,查找,合并,批注,SpecialCells,图形插入

一: 活动单元格:activecell,工作表中活动单元格只有一个 Sub activecells() a activecell.Address 取得活动单元格地址 Cells(2, 3).Activate 激活指定单元格 End Sub selection光标所选区域 Sub 光标所选区域() Selection 1 End Sub Sub …...

【内网安全】横向移动域控提权NetLogonADCSPACKDC永恒之蓝

文章目录章节点横向移动-系统漏洞-CVE-2017-0146(永恒之蓝)影响版本插件检测-横向移动CS联动MSF-检测&利用横向移动-域控提权-CVE-2014-6324横向移动-域控提权-CVE-2020-1472影响版本横向移动-域控提权-CVE-2021-42287前提条件影响版本python版本EXP利用过程C#版本EXP利用过…...

将本地项目上传到远程仓库的步骤

文章目录将本地项目上传到远程仓库的步骤1.进入想上传的项目文件夹2.初始化本地仓库3.添加该项目下的所有文件4.将文件添加到本地仓库中5.添加远程仓库6.将文件更新到远程仓库上7.将本地文件推送回到指定的远程仓库中将本地项目上传到远程仓库的步骤 1.进入想上传的项目文件夹…...

selenium+opencv实现模拟登陆(滑块验证码)

很多网站登录登陆时都要用到滑块验证码,在某些场景例如使用爬虫爬取信息时常常受到阻碍,想着用opencv的模板匹配试试能不能实现模拟登陆。本来觉得网上资料多应该还蛮容易,但实际上手还是搞了蛮久,在这里记录一下整个流程&#xf…...

辽宁申请互联网医院牌照流程

辽宁申请互联网医院牌照流程|沈阳市|大连市|鞍山市|抚顺市|本溪市|丹东市|锦州市|营口市|阜新市|辽阳市|盘锦市|铁岭市|朝阳市|葫芦岛市   很多的人对互联网医院都不是很了解,也不太清楚互联网医院牌照怎么申请,其实牌照申请每个地区都不太一样&#x…...

java实现布隆过滤器

什么是布隆过滤器 布隆过滤器(Bloom Filter)是1970年由布隆提出来的。 它实际上是由一个很长的二进制数组一系列hash算法映射函数,用于判断一个元素是否存在于集合中。 布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和…...

gitlab部署及整合Jenkins持续构建(三)nexus私服的安装及实战、linux安装mysql

文章目录敏捷持续集成是什么?linux安装jdk和maven安装jdk安装mavenlinux安装nexus3.xnexus私服的使用编译安装mysql可能遇到的问题使用cmake时报错敏捷持续集成是什么? 持续集成是一种软件开发实践,即团队开发成员经常集成他们的工作&#x…...

一、Java基础(2)

本章概要 异常的分类及处理 异常的概念异常的分类处理异常的方式 反射机制 动态语言的概念反射机制的概念反射的作用Java 的反射 API反射的过程创建对象的两种方式Method 的 invoke 方法 1.2 异常的分类及处理 1.2.1 异常的概念 异常指在方法不能按正常方式完成时&#xf…...

软件设计师重要知识点——第一章——计算机组成与体系结构

目录 1.1数据的表示 1.2数值表示范围 1.3浮点的运算 1.4计算机结构 1.5计算机体系结构分类——Flynn 1.6指令的基本概念 1.7寻址方式 1.8CISC与RISC 1.9流水线 1.10层次化存储结构 1.11Cache 1.12主存——编址与计算 1.13总线 1.14串联系统与并联系统 1.15N模混…...

编程学习心得

我来写一些,我关于编程的简单认识吧。 我觉得编程是一门艺术,也是一项技能,需要不断地学习和练习。无论是初学者还是有经验的开发人员,都需要耐心和恒心,才能够成为一名优秀的程序员。以下是一些关于编程学习的心得和…...

web获取媒体流

1. 下面例子演示了录屏和截图功能&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport"…...

代码随想录算法训练营第四十二天 | 01背包问题,你该了解这些、01背包问题,你该了解这些 滚动数组、 416. 分割等和子集

打卡第42天&#xff0c;搞搞01背包。 今日任务 01背包问题&#xff0c;你该了解这些&#xff01;01背包问题&#xff0c;你该了解这些&#xff01; 滚动数组416.分割等和子集 背包问题1.0 &#xff1a;0-1 背包 有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weig…...

【Android】JNI静态与动态注册介绍

JNI的两种注册机制&#xff1a;静态注册和动态注册. 一、JNI介绍 JNI(Java Native Interface)&#xff0c;即Java本地接口&#xff0c;JNI是Java调用Native 语言的一种特性。通过JNI可以使得Java与C/C机型交互. 方式&#xff1a; 静态注册动态注册&#xff1a;需要提供Java中…...

【算法题解】22. 接雨水

这是一道 困难 题 题目来自&#xff1a; https://leetcode.cn/problems/trapping-rain-water/ 题目 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 示例 1&#xff1a; 输入&#xff1a;height [0,…...

树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频

使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

【WiFi帧结构】

文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成&#xff1a;MAC头部frame bodyFCS&#xff0c;其中MAC是固定格式的&#xff0c;frame body是可变长度。 MAC头部有frame control&#xff0c;duration&#xff0c;address1&#xff0c;address2&#xff0c;addre…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

多模态图像修复系统:基于深度学习的图片修复实现

多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...

基于Java+VUE+MariaDB实现(Web)仿小米商城

仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意&#xff1a;运行前…...

【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案

目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后&#xff0c;迭代器会失效&#xff0c;因为顺序迭代器在内存中是连续存储的&#xff0c;元素删除后&#xff0c;后续元素会前移。 但一些场景中&#xff0c;我们又需要在执行删除操作…...

Ubuntu系统多网卡多相机IP设置方法

目录 1、硬件情况 2、如何设置网卡和相机IP 2.1 万兆网卡连接交换机&#xff0c;交换机再连相机 2.1.1 网卡设置 2.1.2 相机设置 2.3 万兆网卡直连相机 1、硬件情况 2个网卡n个相机 电脑系统信息&#xff0c;系统版本&#xff1a;Ubuntu22.04.5 LTS&#xff1b;内核版本…...

pgsql:还原数据库后出现重复序列导致“more than one owned sequence found“报错问题的解决

问题&#xff1a; pgsql数据库通过备份数据库文件进行还原时&#xff0c;如果表中有自增序列&#xff0c;还原后可能会出现重复的序列&#xff0c;此时若向表中插入新行时会出现“more than one owned sequence found”的报错提示。 点击菜单“其它”-》“序列”&#xff0c;…...

大模型——基于Docker+DeepSeek+Dify :搭建企业级本地私有化知识库超详细教程

基于Docker+DeepSeek+Dify :搭建企业级本地私有化知识库超详细教程 下载安装Docker Docker官网:https://www.docker.com/ 自定义Docker安装路径 Docker默认安装在C盘,大小大概2.9G,做这行最忌讳的就是安装软件全装C盘,所以我调整了下安装路径。 新建安装目录:E:\MyS…...