qr码是二维码码_SwiftUI中的相机预览和QR码扫描仪-程序员宅基地

qr码是二维码码

In this post, I will guide you through the creation of a QR-code scanner for iOS, using SwiftUI.

在本文中,我将指导您使用SwiftUI创建iOS的QR码扫描仪。

We are also going to see how to create a preview of the camera feed and use it as a SwiftUI View. The end result will be compatible with the simulator, Xcode’s Live Preview as well as UI tests!

我们还将看到如何创建相机提要的预览并将其用作SwiftUI视图。 最终结果将与模拟器,Xcode的Live Preview以及UI测试兼容!

什么是QR码? (What is QR-code?)

QR-code stands for Quick Response Code. They contain small amounts of information presented in such a way that computers and mobile devices can interpret it. QR-codes are a kind of 2D barcodes called Matrix codes. Some variations exist, like Aztec Codes or Data Matrix codes. QR-codes usually look like this:

QR码代表快速响应代码。 它们包含少量信息,这些信息以计算机和移动设备可以解释的方式呈现。 QR码是一种二维码,称为矩阵码。 存在一些变体,例如Aztec代码或Data Matrix代码。 QR码通常如下所示:

入门 (Getting started)

Let’s begin by creating a new iOS app project in Xcode. You will want to choose the Single View App template and make sure the User Interface technology is set to SwiftUI.

让我们从Xcode创建一个新的iOS应用项目开始。 您将要选择Single View App模板,并确保将User Interface技术设置为SwiftUI

Image for post
Create a new Xcode Single View App in Xcode
在Xcode中创建新的Xcode Single View App
Image for post
Run the project to make sure everything is setup
运行项目以确保一切都已设置

准备布局 (Prepare the Layout)

The layout of the scanner screen probably depends on your specific app use case, so we are going to create a very simple view which allows us to see the camera preview, the value of any detected QR-codes as well as a button to toggle the torch light on and off.

扫描仪屏幕的布局可能取决于您特定的应用程序用例,因此我们将创建一个非常简单的视图,使我们可以查看相机预览,任何检测到的QR码的值以及用于切换开启和关闭手电筒。

Image for post

Create the ScannerViewModel, which will hold the state the View

创建ScannerViewModel,它将保留View的状态

The scan interval is a variable which allows us to control how often we are going to retry scanning for a QR-code. This is useful if we want to provide a continuous scan function.

扫描间隔是一个变量,它使我们可以控制重新尝试扫描QR码的频率。 如果我们要提供连续扫描功能,这将很有用。

The torchIsOn field holds the current state of the device torch light. This tutorial assumes that a torch is always available.

torchIsOn字段保存设备手电筒灯的当前状态。 本教程假定割炬始终可用。

The lastQrCode field will hold the string value of the last detected QR-code value. When the user is scanning, this field will update to the last QR-code scanned.

lastQrCode字段将保存最后检测到的QR码值的字符串值。 用户扫描时,此字段将更新为最后扫描的QR码。

Finally a function onFoundQrCode which our QrCodeScanner is going to call whenever a new QR-code has been detected.

最后一个功能onFoundQrCode ,我们的QrCodeScanner是怎么回事时已检测到新的QR码来调用。

Now let’s create the ScannerView layout

现在让我们创建ScannerView布局

We are going to use a ZStack to create a layout where the Scanner showing the camera view will be seen at the back, taking the entire screen and on top of it, we are going to layout some interface elements like the balloon with the recently scanned QR-code or the torch button.

我们将使用ZStack来创建一个布局,在该布局中,可以在背面看到显示摄像机视图的Scanner,并占据整个屏幕,并在其顶部,我们将使用最近扫描的内容来布局一些界面元素,例如气球QR码或手电筒按钮。

关于相机视图 (About the Camera View)

We are going to create a View which shows the feed from the device camera. Ideally, we also want to be able to position the Camera View using SwiftUI.

我们将创建一个视图,该视图显示来自设备相机的提要。 理想情况下,我们还希望能够使用SwiftUI定位Camera View。

Most of the functionality we are going to use comes from the AVFoundation framework. For presently it doesn’t offer any ready made SwiftUI views, we are going to create a traditional UIView and embed it as a UIViewRepresentable in our SwiftUI app.

我们将要使用的大多数功能来自AVFoundation框架。 目前,它不提供任何现成的SwiftUI视图,我们将创建一个传统的UIView并将其作为UIViewRepresentable嵌入到我们的SwiftUI应用中。

We are going to setup a AVCaptureSession which will use the device back camera as an input and a AVCaptureMetadataOutput as an output, allowing us to receive a stream of metadata objects recognised from the camera input. Those metadata objects are the actual QR-code values we are aiming to gather.

我们将设置一个AVCaptureSession ,它将使用设备后置摄像头作为输入,将AVCaptureMetadataOutput用作输出,从而使我们能够接收从摄像头输入中识别出的元数据对象流。 这些元数据对象是我们旨在收集的实际QR码值。

Since we are going to use the camera view in SwiftUI layouts, it will be ideal if the implementation plays nice with the simulator (so the SwiftUI preview function will work). Since the simulator lacks a physical camera device, we are going to embed a fallback in the camera view.

由于我们将在SwiftUI布局中使用摄影机视图,因此如果实现与模拟器完美配合将是理想的选择(因此SwiftUI预览功能将起作用)。 由于模拟器缺少物理相机设备,因此我们将在相机视图中嵌入一个备用。

代表 (The Delegate)

The delegate will be responsible for handling the metadata output, checking if a QR-code was found and informing the parent View of that QR-code value.

委托人将负责处理元数据输出,检查是否找到QR码,并将该QR码值通知父视图。

Most notably, our delegate object will adopt the AVCaptureMetadataOutputObjectsDelegate protocol in order to listen for new metadata objects which were detected in the camera feed.

最值得注意的是,我们的委托对象将采用AVCaptureMetadataOutputObjectsDelegate协议,以侦听在相机供稿中检测到的AVCaptureMetadataOutputObjectsDelegate数据对象。

The delegate will also take advantage of the scanning interval we prepared for in our View Model. As long as the capture session is active and a QR-code image is in view of the camera feed, new metadata objects will be constantly detected. For this, we are going to skip frames and only notify the parent view once per scanning interval.

委托还将利用我们在视图模型中准备的扫描间隔。 只要捕获会话处于活动状态并且QR码图像在摄像机馈送的视角下,就会不断检测到新的元数据对象。 为此,我们将跳过帧,并且每个扫描间隔仅通知一次父视图。

相机预览 (The CameraPreview)

The camera preview is the UIView we are going to use to show a live feed from the camera (or a simulated value for the simulator). This is a UIKit view which will eventually be presented using a UIViewRepresentable in our SwiftUI layout.

相机预览是UIView我们将使用它来显示相机的实时供稿(或模拟器的模拟值)。 这是一个UIKit视图,最终将在我们的SwiftUI布局中使用UIViewRepresentable进行呈现。

The view is created for a given AVCaptureSession and includes a AVCaptureVideoPreviewLayer which is based on CoreAnimation and enables us to preview the visual output from the camera session. This is what the user will eventually see as a “camera preview”. When the camera is not available, we are going to substitute the vide preview with a simple UILabel showing the mock data content we’ve provided.

该视图是为给定的AVCaptureSession创建的,并包括一个基于CoreAnimation的AVCaptureVideoPreviewLayer ,使我们能够预览摄像头会话的视觉输出。 这就是用户最终将看到的“相机预览”。 当摄像机不可用时,我们将用一个简单的UILabel代替视频预览,该UILabel显示我们提供的模拟数据内容。

This means a QR-code scan can be “simulated” during preview or live view in Xcode, the simulator or a UI test.

这意味着可以在Xcode,模拟器或UI测试的预览或实时取景期间“模拟” QR码扫描。

几乎在那里,创建UIViewRepresentable (Almost there, creating the UIViewRepresentable)

The last piece we need is a way to show the CameraPreview view in SwiftUI. This can be achieved by implementing the framework-provided UIViewRepresentable protocol.

我们需要的最后一块是在SwiftUI中显示CameraPreview视图的方法。 这可以通过实现框架提供的UIViewRepresentable协议来实现。

The purpose of this protocol is for us to sort of translate the SwiftUI state and lifecycle events to UIKit. For example, in SwiftUI views are often destroyed and recreated when their state changes while in UIKit a UIView is usually kept around and updated.

该协议的目的是让我们将SwiftUI状态和生命周期事件转换为UIKit。 例如,在SwiftUI中,视图的状态更改时通常会销毁并重新创建视图,而在UIKit中,通常会保留并更新UIView。

The bare minimum we are going to need is:

我们需要的最低要求是:

  • Create a CameraView and associate it with a AVCaptureSession.

    创建一个CameraView并将其与AVCaptureSession关联。

  • Check if we are running on a real device and if it is the case, request permission to access the camera.

    检查我们是否在真实设备上运行,如果是,请请求访问摄像机的权限。

Remember to add the NSCameraUsageDescription key to the Info.plist file otherwise using the camera will result in a crash.

请记住将 NSCameraUsageDescription 添加 Info.plist 文件,否则使用相机会导致崩溃。

  • When the SwiftUI view is updated, we need to make sure the CameraView will also update its layout.

    更新SwiftUI视图时,我们需要确保CameraView也将更新其布局。
  • We need to correctly dispose of the capture session when SwiftUI is preparing to remove and destroy the QrCodeScannerView.

    当SwiftUI准备删除和销毁QrCodeScannerView时,我们需要正确处理捕获会话。

Let’s tweak the QrCodeScannerView with the following additions:

让我们对QrCodeScannerView进行以下调整:

  • The ability to request permission to use the camera

    要求许可使用相机的能力
  • The ability to setup the scanning interval from the SwiftUI view as a modifier.

    从SwiftUI视图设置扫描间隔作为修改器的功能。
  • The ability to set the mock data for use during simulation or UI Testing.

    设置模拟数据以在仿真或UI测试期间使用的能力。
  • The ability to control the torch light of the device.

    控制设备的手电筒的能力。

Here is the complete implementation of the scanner view:

这是扫描器视图的完整实现:

结束 (The End)

Now we can use the QrCodeScannerView in the SwiftUI layout. Replace the Text view with the following:

现在我们可以在SwiftUI布局中使用QrCodeScannerView了。 将文本视图替换为以下内容:

QrCodeScannerView()
.found(r: self.viewModel.onFoundQrCode)
.torchLight(isOn: self.viewModel.torchIsOn)
.interval(delay: self.viewModel.scanInterval)

Tadaa

多田a

Image for post
Kodos app for macOS! Kodos应用程序打个招呼!
Image for post

翻译自: https://medium.com/dev-genius/camera-preview-and-a-qr-code-scanner-in-swiftui-48b111155c66

qr码是二维码码

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_26638123/article/details/108171550

智能推荐

使用nginx解决浏览器跨域问题_nginx不停的xhr-程序员宅基地

文章浏览阅读1k次。通过使用ajax方法跨域请求是浏览器所不允许的,浏览器出于安全考虑是禁止的。警告信息如下:不过jQuery对跨域问题也有解决方案,使用jsonp的方式解决,方法如下:$.ajax({ async:false, url: 'http://www.mysite.com/demo.do', // 跨域URL ty..._nginx不停的xhr

在 Oracle 中配置 extproc 以访问 ST_Geometry-程序员宅基地

文章浏览阅读2k次。关于在 Oracle 中配置 extproc 以访问 ST_Geometry,也就是我们所说的 使用空间SQL 的方法,官方文档链接如下。http://desktop.arcgis.com/zh-cn/arcmap/latest/manage-data/gdbs-in-oracle/configure-oracle-extproc.htm其实简单总结一下,主要就分为以下几个步骤。..._extproc

Linux C++ gbk转为utf-8_linux c++ gbk->utf8-程序员宅基地

文章浏览阅读1.5w次。linux下没有上面的两个函数,需要使用函数 mbstowcs和wcstombsmbstowcs将多字节编码转换为宽字节编码wcstombs将宽字节编码转换为多字节编码这两个函数,转换过程中受到系统编码类型的影响,需要通过设置来设定转换前和转换后的编码类型。通过函数setlocale进行系统编码的设置。linux下输入命名locale -a查看系统支持的编码_linux c++ gbk->utf8

IMP-00009: 导出文件异常结束-程序员宅基地

文章浏览阅读750次。今天准备从生产库向测试库进行数据导入,结果在imp导入的时候遇到“ IMP-00009:导出文件异常结束” 错误,google一下,发现可能有如下原因导致imp的数据太大,没有写buffer和commit两个数据库字符集不同从低版本exp的dmp文件,向高版本imp导出的dmp文件出错传输dmp文件时,文件损坏解决办法:imp时指定..._imp-00009导出文件异常结束

python程序员需要深入掌握的技能_Python用数据说明程序员需要掌握的技能-程序员宅基地

文章浏览阅读143次。当下是一个大数据的时代,各个行业都离不开数据的支持。因此,网络爬虫就应运而生。网络爬虫当下最为火热的是Python,Python开发爬虫相对简单,而且功能库相当完善,力压众多开发语言。本次教程我们爬取前程无忧的招聘信息来分析Python程序员需要掌握那些编程技术。首先在谷歌浏览器打开前程无忧的首页,按F12打开浏览器的开发者工具。浏览器开发者工具是用于捕捉网站的请求信息,通过分析请求信息可以了解请..._初级python程序员能力要求

Spring @Service生成bean名称的规则(当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致)_@service beanname-程序员宅基地

文章浏览阅读7.6k次,点赞2次,收藏6次。@Service标注的bean,类名:ABDemoService查看源码后发现,原来是经过一个特殊处理:当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致public class AnnotationBeanNameGenerator implements BeanNameGenerator { private static final String C..._@service beanname

随便推点

二叉树的各种创建方法_二叉树的建立-程序员宅基地

文章浏览阅读6.9w次,点赞73次,收藏463次。1.前序创建#include<stdio.h>#include<string.h>#include<stdlib.h>#include<malloc.h>#include<iostream>#include<stack>#include<queue>using namespace std;typed_二叉树的建立

解决asp.net导出excel时中文文件名乱码_asp.net utf8 导出中文字符乱码-程序员宅基地

文章浏览阅读7.1k次。在Asp.net上使用Excel导出功能,如果文件名出现中文,便会以乱码视之。 解决方法: fileName = HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8);_asp.net utf8 导出中文字符乱码

笔记-编译原理-实验一-词法分析器设计_对pl/0作以下修改扩充。增加单词-程序员宅基地

文章浏览阅读2.1k次,点赞4次,收藏23次。第一次实验 词法分析实验报告设计思想词法分析的主要任务是根据文法的词汇表以及对应约定的编码进行一定的识别,找出文件中所有的合法的单词,并给出一定的信息作为最后的结果,用于后续语法分析程序的使用;本实验针对 PL/0 语言 的文法、词汇表编写一个词法分析程序,对于每个单词根据词汇表输出: (单词种类, 单词的值) 二元对。词汇表:种别编码单词符号助记符0beginb..._对pl/0作以下修改扩充。增加单词

android adb shell 权限,android adb shell权限被拒绝-程序员宅基地

文章浏览阅读773次。我在使用adb.exe时遇到了麻烦.我想使用与bash相同的adb.exe shell提示符,所以我决定更改默认的bash二进制文件(当然二进制文件是交叉编译的,一切都很完美)更改bash二进制文件遵循以下顺序> adb remount> adb push bash / system / bin /> adb shell> cd / system / bin> chm..._adb shell mv 权限

投影仪-相机标定_相机-投影仪标定-程序员宅基地

文章浏览阅读6.8k次,点赞12次,收藏125次。1. 单目相机标定引言相机标定已经研究多年,标定的算法可以分为基于摄影测量的标定和自标定。其中,应用最为广泛的还是张正友标定法。这是一种简单灵活、高鲁棒性、低成本的相机标定算法。仅需要一台相机和一块平面标定板构建相机标定系统,在标定过程中,相机拍摄多个角度下(至少两个角度,推荐10~20个角度)的标定板图像(相机和标定板都可以移动),即可对相机的内外参数进行标定。下面介绍张氏标定法(以下也这么称呼)的原理。原理相机模型和单应矩阵相机标定,就是对相机的内外参数进行计算的过程,从而得到物体到图像的投影_相机-投影仪标定

Wayland架构、渲染、硬件支持-程序员宅基地

文章浏览阅读2.2k次。文章目录Wayland 架构Wayland 渲染Wayland的 硬件支持简 述: 翻译一篇关于和 wayland 有关的技术文章, 其英文标题为Wayland Architecture .Wayland 架构若是想要更好的理解 Wayland 架构及其与 X (X11 or X Window System) 结构;一种很好的方法是将事件从输入设备就开始跟踪, 查看期间所有的屏幕上出现的变化。这就是我们现在对 X 的理解。 内核是从一个输入设备中获取一个事件,并通过 evdev 输入_wayland

推荐文章

热门文章

相关标签