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

SwiftUI调用相机拍照

在 SwiftUI 中实现拍照功能,需要结合 UIViewControllerRepresentableUIImagePickerController 来实现相机功能。下面是一个详细的示例,展示如何使用 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()}
}

解释

  1. ImagePicker 组件

    • UIViewControllerRepresentable 协议用来将 UIImagePickerController 引入 SwiftUI。
    • makeUIViewControllerupdateUIViewController 方法创建和更新 UIImagePickerController
    • Coordinator 类作为 UIImagePickerController 的代理,处理图片选择和取消操作。
  2. ContentView

    • 使用 @State 属性包装变量 isImagePickerPresented 来控制 ImagePicker 的显示。
    • 使用 @State 属性包装变量 selectedImage 来存储选取的图片。
    • 当点击 “Take Photo” 按钮时,显示 ImagePicker
    • sheet 修饰符用于在 isImagePickerPresentedtrue 时呈现 ImagePicker

通过这种方式,你可以在 SwiftUI 应用中实现拍照功能。请注意,拍照功能只能在真实设备上使用,因为模拟器不支持摄像头。

在 iOS 应用中访问相机需要在 Info.plist 文件中添加 NSCameraUsageDescription 键,以告知用户为什么需要访问相机。否则,应用在尝试访问相机时会崩溃。

添加 NSCameraUsageDescriptionInfo.plist

  1. 打开你的 Xcode 项目。

  2. 在项目导航中,找到并点击你的 Info.plist 文件。

  3. 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 的图形化界面,可以按以下步骤操作:

  1. 打开 Info.plist 文件。
  2. 点击右键选择 “Add Row”。
  3. 在新行的键列中输入 NSCameraUsageDescription
  4. 在值列中输入对用户的说明,比如 “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 中实现拍照功能&#xff0c;需要结合 UIViewControllerRepresentable 和 UIImagePickerController 来实现相机功能。下面是一个详细的示例&#xff0c;展示如何使用 SwiftUI 来实现拍照功能&#xff1a; 1. 创建一个 ImagePicker 组件 首先&#xff0c;创建一个 U…...

elasticsearch (dsl)

正排索引 和 倒排索引 正排索引&#xff1a;通过id &#xff0c;查询content 倒排索引&#xff1a;通过content&#xff0c;查询到符合的 ids eg&#xff1a; 正排索引就是通过《静夜思》&#xff0c;找到整片文章。 倒排索引通过“明月”&#xff0c;找到《静夜思》 《望…...

聊聊大模型微调训练全流程的思考

前言 参考现有的中文医疗模型&#xff1a;MedicalGPT、CareGPT等领域模型的训练流程&#xff0c;结合ChatGPT的训练流程&#xff0c;总结如下&#xff1a; 在预训练阶段&#xff0c;模型会从大量无标注文本数据集中学习领域/通用知识&#xff1b;其次使用{有监督微调}(SFT)优化…...

Python变量符号:深入探索与实用指南

Python变量符号&#xff1a;深入探索与实用指南 在Python编程的世界中&#xff0c;变量符号扮演着至关重要的角色。它们不仅是存储数据的容器&#xff0c;更是构建复杂逻辑和算法的基础。然而&#xff0c;对于初学者来说&#xff0c;Python的变量符号可能会带来一些困惑和挑战…...

实验八 页面置换模拟程序设计

网上找到的程序得到的答案经过手算验证是错的&#xff0c;所以自己实现了一个&#xff0c;具体实现看代码吧&#xff0c;多余的操作已经去掉了。 #include <stdio.h> #include <stdlib.h> #include <stdbool.h>#define VM_PAGE 7 /*假设每个页面可以存放10…...

Spring类加载机制揭秘:深度解析“卸载”阶段

1. 引言 在Spring框架中&#xff0c;类的加载和卸载是一个复杂但至关重要的过程。加载主要涉及将类的字节码加载到JVM中&#xff0c;创建对应的Class对象&#xff0c;并准备使其可用的过程。而卸载&#xff0c;则是指当一个类不再被需要时&#xff0c;将其从JVM中清除&#xf…...

Jupyter Notebook快速搭建

Jupyter Notebook why Jupyter Notebook Jupyter Notebook 是一个开源的 Web 应用程序&#xff0c;允许你创建和分享包含实时代码、方程、可视化和解释性文本的文档。其应用包括&#xff1a;数据清洗和转换、数值模拟、统计建模、数据可视化、机器学习等等。 Jupyter Notebo…...

Linux C语言:数组的定义和初始化

一、数组 1、定义 在程序设计中&#xff0c;为了处理方便&#xff0c;把具有相同类型的若干变量按有序的形式组织起来&#xff0c;具有一定顺序关系的若干个变量的集合就是数组 。 2、特点 组成数组的各个变量称为数组的元素数组中各元素的数据类型要求相同元素在内存中是连…...

spring框架限制接口是否要登录过才能访问

1、引入spring 、spring boot依赖&#xff0c;这部分不再多说&#xff0c;正常开发spring boot项目就可以。 2、定义类&#xff0c;实现WebMvcConfigurer接口 package com.hmblogs.config;import com.hmblogs.config.web.interceptor.PortalTokenInterceptor; import org.spri…...

【全开源】废品回收垃圾回收小程序APP公众号源码PHP版本

&#x1f31f;废品回收小程序&#xff1a;绿色生活的新助手&#x1f331; 一、引言 随着环保意识的逐渐提高&#xff0c;废品回收成为了我们日常生活中的重要一环。但是&#xff0c;如何更方便、高效地进行废品回收呢&#xff1f;今天&#xff0c;我要向大家推荐一款超级实用…...

勒索软件分析_目标文件扫描行为分析

BlackBasta首先通过 FindFirstVolumeW 与 FindNextVolumeW 实现系统中第一个卷的搜索和其余卷的遍历,之后通过 GetVolumePathNamesForVolumeNameW 检索指定卷的驱动器号和挂载的文件夹路径列表,然后通过 GetVolumeInformationW 获取关于指定卷的信息,具体代码如下所示。 Fin…...

2024050401-重学 Java 设计模式《实战代理模式》

重学 Java 设计模式&#xff1a;实战代理模式「模拟mybatis-spring中定义DAO接口&#xff0c;使用代理类方式操作数据库原理实现场景」 一、前言 难以跨越的瓶颈期&#xff0c;把你拿捏滴死死的&#xff01; 编程开发学习过程中遇到的瓶颈期&#xff0c;往往是由于看不到前进…...

HTML跨年烟花

目录 写在前面 关于小编 HTML简介 程序设计 系列文章 写在后面 写在前面 学会了这个html烟花秀&#xff0c;跨年就不缺文案喽~ 关于小编 平易近人&#xff0c;慈眉善目&#xff0c;爱交朋友&#xff0c;舍己为人&#xff0c;和蔼可亲&#xff0c;能说会道&#xff0c;…...

微服务第二轮

学习文档 背景 由于每个微服务都有不同的地址或端口&#xff0c;入口不同 请求不同数据时要访问不同的入口&#xff0c;需要维护多个入口地址&#xff0c;麻烦 前端无法调用nacos&#xff0c;无法实时更新服务列表 单体架构时我们只需要完成一次用户登录、身份校验&#xff…...

线性模型-分类

一、线性判别分析LDA 线性判别分析是一种经典的线性学习方法&#xff0c;在二分类问题上最早是Fisher提出的&#xff0c;亦称为Fisher判别分析。 Fisher判别分析是一种用于降维和分类的统计方法&#xff0c;旨在找到可以最好区分不同类别的特征。它基于类内方差和类间方差的比…...

OpenAI前董事会成员称Sam Altman因 “ 向董事会撒谎 ” 而被解雇

据前 OpenAI 董事会成员称&#xff0c;据称 Altman 隐瞒了他对 OpenAI 创业基金的所有权。 更详细的内容请参考原文&#xff1a; https://cointelegraph.com/news/sam-altman-fired-openai-board-allegations 据一位前董事会成员称&#xff0c;Sam Altman 因涉嫌向董事会隐瞒…...

【启明智显分享】WIFI6开发板ZX6010:开源OpenWrt SDK,接受定制!

在数字化飞速发展的当下&#xff0c;网络速度和稳定性已成为各行各业不可或缺的关键因素。今天&#xff0c;我们为大家推荐一款基于IPQ6010的AX1800方案ZX6010 Wi-Fi6开发板&#xff0c;为您的网络世界注入强大动力。 一、超强硬件配置 ZX6010搭载IPQ6010四核ARM Cortex A53处…...

C语言能否使⽤ fflush( ) 函数清除多余的输⼊?

一、问题 在从终端输⼊数据时&#xff0c;很可能会输⼊多余的数据&#xff0c;那么能否使⽤ fflush( ) 函数清除呢&#xff1f; 二、解答 fflush( ) 函数只是⽤在⽂件以写的⽅式打开时&#xff0c;将缓冲区内容写⼊到⽂件。因此 fflush( ) 函数仅对输出流有效&#xff0c;对输…...

如何把试卷上的字去掉再打印?分享三种方法

如何把试卷上的字去掉再打印&#xff1f;随着科技的不断发展&#xff0c;现代教育和学习方式也在逐渐变革。在学习过程中&#xff0c;我们经常需要对试卷进行整理和分析&#xff0c;以便更好地掌握知识点和复习。然而&#xff0c;传统的试卷整理方法往往效率低下且容易出错。幸…...

Android开机动画压缩包zip,自制开机动画(基于Android10.0.0-r41)

文章目录 Android开机动画压缩包zip&#xff0c;自制开机动画1.Android加载压缩包原理2.自制开机动画 Android开机动画压缩包zip&#xff0c;自制开机动画 1.Android加载压缩包原理 这里有个md文件我们看下 核心部分, 首先要创建一个文件叫做desc.txt&#xff0c;这是规定的…...

python打卡day49

知识点回顾&#xff1a; 通道注意力模块复习空间注意力模块CBAM的定义 作业&#xff1a;尝试对今天的模型检查参数数目&#xff0c;并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一&#xff09; 1. CSI-2层定义&#xff08;CSI-2 Layer Definitions&#xff09; 分层结构 &#xff1a;CSI-2协议分为6层&#xff1a; 物理层&#xff08;PHY Layer&#xff09; &#xff1a; 定义电气特性、时钟机制和传输介质&#xff08;导线&#…...

1688商品列表API与其他数据源的对接思路

将1688商品列表API与其他数据源对接时&#xff0c;需结合业务场景设计数据流转链路&#xff0c;重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点&#xff1a; 一、核心对接场景与目标 商品数据同步 场景&#xff1a;将1688商品信息…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架&#xff0c;支持"一次开发&#xff0c;多端部署"&#xff0c;可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务&#xff0c;为旅游应用带来&#xf…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

Spring Boot面试题精选汇总

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

vue3 定时器-定义全局方法 vue+ts

1.创建ts文件 路径&#xff1a;src/utils/timer.ts 完整代码&#xff1a; import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

深度学习习题2

1.如果增加神经网络的宽度&#xff0c;精确度会增加到一个特定阈值后&#xff0c;便开始降低。造成这一现象的可能原因是什么&#xff1f; A、即使增加卷积核的数量&#xff0c;只有少部分的核会被用作预测 B、当卷积核数量增加时&#xff0c;神经网络的预测能力会降低 C、当卷…...