SwiftUI调用相机拍照
在 SwiftUI 中实现拍照功能,需要结合 UIViewControllerRepresentable 和 UIImagePickerController 来实现相机功能。下面是一个详细的示例,展示如何使用 SwiftUI 来实现拍照功能:
1. 创建一个 ImagePicker 组件
首先,创建一个 UIViewControllerRepresentable 结构,用于包装 UIImagePickerController。
import SwiftUI
import UIKitstruct ImagePicker: UIViewControllerRepresentable {@Binding var selectedImage: UIImage?@Environment(\.presentationMode) var presentationModevar sourceType: UIImagePickerController.SourceType = .cameraclass Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {let parent: ImagePickerinit(parent: ImagePicker) {self.parent = parent}func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {if let image = info[.originalImage] as? UIImage {parent.selectedImage = image}parent.presentationMode.wrappedValue.dismiss()}func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {parent.presentationMode.wrappedValue.dismiss()}}func makeCoordinator() -> Coordinator {Coordinator(parent: self)}func makeUIViewController(context: Context) -> UIImagePickerController {let picker = UIImagePickerController()picker.delegate = context.coordinatorpicker.sourceType = sourceTypereturn picker}func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {}
}
2. 使用 ImagePicker 组件
接下来,在你的主视图中使用 ImagePicker 组件来实现拍照功能。
import SwiftUIstruct ContentView: View {@State private var isImagePickerPresented = false@State private var selectedImage: UIImage?var body: some View {VStack {if let selectedImage = selectedImage {Image(uiImage: selectedImage).resizable().scaledToFit().frame(width: 300, height: 300)} else {Text("No Image Selected").frame(width: 300, height: 300).background(Color.gray)}Button(action: {isImagePickerPresented = true}) {Text("Take Photo").padding().background(Color.blue).foregroundColor(.white).cornerRadius(10)}.padding()}.sheet(isPresented: $isImagePickerPresented) {ImagePicker(selectedImage: $selectedImage)}}
}struct ContentView_Previews: PreviewProvider {static var previews: some View {ContentView()}
}
解释
-
ImagePicker组件:UIViewControllerRepresentable协议用来将UIImagePickerController引入 SwiftUI。makeUIViewController和updateUIViewController方法创建和更新UIImagePickerController。Coordinator类作为UIImagePickerController的代理,处理图片选择和取消操作。
-
ContentView:- 使用
@State属性包装变量isImagePickerPresented来控制ImagePicker的显示。 - 使用
@State属性包装变量selectedImage来存储选取的图片。 - 当点击 “Take Photo” 按钮时,显示
ImagePicker。 sheet修饰符用于在isImagePickerPresented为true时呈现ImagePicker。
- 使用
通过这种方式,你可以在 SwiftUI 应用中实现拍照功能。请注意,拍照功能只能在真实设备上使用,因为模拟器不支持摄像头。
在 iOS 应用中访问相机需要在 Info.plist 文件中添加 NSCameraUsageDescription 键,以告知用户为什么需要访问相机。否则,应用在尝试访问相机时会崩溃。
添加 NSCameraUsageDescription 到 Info.plist
-
打开你的 Xcode 项目。
-
在项目导航中,找到并点击你的
Info.plist文件。 -
在
Info.plist中,添加一个新的键值对:- 键:
NSCameraUsageDescription - 值:解释你的应用需要使用相机的原因,比如 “This app requires access to the camera to take photos.”
- 键:
示例:
<key>NSCameraUsageDescription</key>
<string>This app requires access to the camera to take photos.</string>
如果你使用 Xcode 的图形化界面,可以按以下步骤操作:
- 打开
Info.plist文件。 - 点击右键选择 “Add Row”。
- 在新行的键列中输入
NSCameraUsageDescription。 - 在值列中输入对用户的说明,比如 “This app requires access to the camera to take photos.”
更新后的示例代码
完成上述步骤后,你可以重新运行之前的代码:
import SwiftUI
import UIKitstruct ImagePicker: UIViewControllerRepresentable {@Binding var selectedImage: UIImage?@Environment(\.presentationMode) var presentationModevar sourceType: UIImagePickerController.SourceType = .cameraclass Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {let parent: ImagePickerinit(parent: ImagePicker) {self.parent = parent}func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {if let image = info[.originalImage] as? UIImage {parent.selectedImage = image}parent.presentationMode.wrappedValue.dismiss()}func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {parent.presentationMode.wrappedValue.dismiss()}}func makeCoordinator() -> Coordinator {Coordinator(parent: self)}func makeUIViewController(context: Context) -> UIImagePickerController {let picker = UIImagePickerController()picker.delegate = context.coordinatorpicker.sourceType = sourceTypereturn picker}func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {}
}struct ContentView: View {@State private var isImagePickerPresented = false@State private var selectedImage: UIImage?var body: some View {VStack {if let selectedImage = selectedImage {Image(uiImage: selectedImage).resizable().scaledToFit().frame(width: 300, height: 300)} else {Text("No Image Selected").frame(width: 300, height: 300).background(Color.gray)}Button(action: {isImagePickerPresented = true}) {Text("Take Photo").padding().background(Color.blue).foregroundColor(.white).cornerRadius(10)}.padding()}.sheet(isPresented: $isImagePickerPresented) {ImagePicker(selectedImage: $selectedImage)}}
}struct ContentView_Previews: PreviewProvider {static var previews: some View {ContentView()}
}
通过添加 NSCameraUsageDescription,应用在请求访问相机时会向用户显示一条提示,解释为什么需要访问相机,从而避免因未声明权限而导致的崩溃。
相关文章:
SwiftUI调用相机拍照
在 SwiftUI 中实现拍照功能,需要结合 UIViewControllerRepresentable 和 UIImagePickerController 来实现相机功能。下面是一个详细的示例,展示如何使用 SwiftUI 来实现拍照功能: 1. 创建一个 ImagePicker 组件 首先,创建一个 U…...
elasticsearch (dsl)
正排索引 和 倒排索引 正排索引:通过id ,查询content 倒排索引:通过content,查询到符合的 ids eg: 正排索引就是通过《静夜思》,找到整片文章。 倒排索引通过“明月”,找到《静夜思》 《望…...
聊聊大模型微调训练全流程的思考
前言 参考现有的中文医疗模型:MedicalGPT、CareGPT等领域模型的训练流程,结合ChatGPT的训练流程,总结如下: 在预训练阶段,模型会从大量无标注文本数据集中学习领域/通用知识;其次使用{有监督微调}(SFT)优化…...
Python变量符号:深入探索与实用指南
Python变量符号:深入探索与实用指南 在Python编程的世界中,变量符号扮演着至关重要的角色。它们不仅是存储数据的容器,更是构建复杂逻辑和算法的基础。然而,对于初学者来说,Python的变量符号可能会带来一些困惑和挑战…...
实验八 页面置换模拟程序设计
网上找到的程序得到的答案经过手算验证是错的,所以自己实现了一个,具体实现看代码吧,多余的操作已经去掉了。 #include <stdio.h> #include <stdlib.h> #include <stdbool.h>#define VM_PAGE 7 /*假设每个页面可以存放10…...
Spring类加载机制揭秘:深度解析“卸载”阶段
1. 引言 在Spring框架中,类的加载和卸载是一个复杂但至关重要的过程。加载主要涉及将类的字节码加载到JVM中,创建对应的Class对象,并准备使其可用的过程。而卸载,则是指当一个类不再被需要时,将其从JVM中清除…...
Jupyter Notebook快速搭建
Jupyter Notebook why Jupyter Notebook Jupyter Notebook 是一个开源的 Web 应用程序,允许你创建和分享包含实时代码、方程、可视化和解释性文本的文档。其应用包括:数据清洗和转换、数值模拟、统计建模、数据可视化、机器学习等等。 Jupyter Notebo…...
Linux C语言:数组的定义和初始化
一、数组 1、定义 在程序设计中,为了处理方便,把具有相同类型的若干变量按有序的形式组织起来,具有一定顺序关系的若干个变量的集合就是数组 。 2、特点 组成数组的各个变量称为数组的元素数组中各元素的数据类型要求相同元素在内存中是连…...
spring框架限制接口是否要登录过才能访问
1、引入spring 、spring boot依赖,这部分不再多说,正常开发spring boot项目就可以。 2、定义类,实现WebMvcConfigurer接口 package com.hmblogs.config;import com.hmblogs.config.web.interceptor.PortalTokenInterceptor; import org.spri…...
【全开源】废品回收垃圾回收小程序APP公众号源码PHP版本
🌟废品回收小程序:绿色生活的新助手🌱 一、引言 随着环保意识的逐渐提高,废品回收成为了我们日常生活中的重要一环。但是,如何更方便、高效地进行废品回收呢?今天,我要向大家推荐一款超级实用…...
勒索软件分析_目标文件扫描行为分析
BlackBasta首先通过 FindFirstVolumeW 与 FindNextVolumeW 实现系统中第一个卷的搜索和其余卷的遍历,之后通过 GetVolumePathNamesForVolumeNameW 检索指定卷的驱动器号和挂载的文件夹路径列表,然后通过 GetVolumeInformationW 获取关于指定卷的信息,具体代码如下所示。 Fin…...
2024050401-重学 Java 设计模式《实战代理模式》
重学 Java 设计模式:实战代理模式「模拟mybatis-spring中定义DAO接口,使用代理类方式操作数据库原理实现场景」 一、前言 难以跨越的瓶颈期,把你拿捏滴死死的! 编程开发学习过程中遇到的瓶颈期,往往是由于看不到前进…...
HTML跨年烟花
目录 写在前面 关于小编 HTML简介 程序设计 系列文章 写在后面 写在前面 学会了这个html烟花秀,跨年就不缺文案喽~ 关于小编 平易近人,慈眉善目,爱交朋友,舍己为人,和蔼可亲,能说会道,…...
微服务第二轮
学习文档 背景 由于每个微服务都有不同的地址或端口,入口不同 请求不同数据时要访问不同的入口,需要维护多个入口地址,麻烦 前端无法调用nacos,无法实时更新服务列表 单体架构时我们只需要完成一次用户登录、身份校验ÿ…...
线性模型-分类
一、线性判别分析LDA 线性判别分析是一种经典的线性学习方法,在二分类问题上最早是Fisher提出的,亦称为Fisher判别分析。 Fisher判别分析是一种用于降维和分类的统计方法,旨在找到可以最好区分不同类别的特征。它基于类内方差和类间方差的比…...
OpenAI前董事会成员称Sam Altman因 “ 向董事会撒谎 ” 而被解雇
据前 OpenAI 董事会成员称,据称 Altman 隐瞒了他对 OpenAI 创业基金的所有权。 更详细的内容请参考原文: https://cointelegraph.com/news/sam-altman-fired-openai-board-allegations 据一位前董事会成员称,Sam Altman 因涉嫌向董事会隐瞒…...
【启明智显分享】WIFI6开发板ZX6010:开源OpenWrt SDK,接受定制!
在数字化飞速发展的当下,网络速度和稳定性已成为各行各业不可或缺的关键因素。今天,我们为大家推荐一款基于IPQ6010的AX1800方案ZX6010 Wi-Fi6开发板,为您的网络世界注入强大动力。 一、超强硬件配置 ZX6010搭载IPQ6010四核ARM Cortex A53处…...
C语言能否使⽤ fflush( ) 函数清除多余的输⼊?
一、问题 在从终端输⼊数据时,很可能会输⼊多余的数据,那么能否使⽤ fflush( ) 函数清除呢? 二、解答 fflush( ) 函数只是⽤在⽂件以写的⽅式打开时,将缓冲区内容写⼊到⽂件。因此 fflush( ) 函数仅对输出流有效,对输…...
如何把试卷上的字去掉再打印?分享三种方法
如何把试卷上的字去掉再打印?随着科技的不断发展,现代教育和学习方式也在逐渐变革。在学习过程中,我们经常需要对试卷进行整理和分析,以便更好地掌握知识点和复习。然而,传统的试卷整理方法往往效率低下且容易出错。幸…...
Android开机动画压缩包zip,自制开机动画(基于Android10.0.0-r41)
文章目录 Android开机动画压缩包zip,自制开机动画1.Android加载压缩包原理2.自制开机动画 Android开机动画压缩包zip,自制开机动画 1.Android加载压缩包原理 这里有个md文件我们看下 核心部分, 首先要创建一个文件叫做desc.txt,这是规定的…...
C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...
React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)
宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
SpringCloudGateway 自定义局部过滤器
场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...
Go语言多线程问题
打印零与奇偶数(leetcode 1116) 方法1:使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...
django blank 与 null的区别
1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...
aardio 自动识别验证码输入
技术尝试 上周在发学习日志时有网友提议“在网页上识别验证码”,于是尝试整合图像识别与网页自动化技术,完成了这套模拟登录流程。核心思路是:截图验证码→OCR识别→自动填充表单→提交并验证结果。 代码在这里 import soImage; import we…...
