iOS 系统提供的媒体资源选择器(UIImagePickerController)
简介
图片或者视频的选择功能几乎是每个APP必不可少的,UIImagePickerController 是 iOS 系统提供的一个方便的媒体选择器,允许用户从照片库中选择图片或视频,或者使用相机拍摄新照片和视频。
它的页面简单易用,代码稳定可靠,适合用于单张图片或者视频的选择场景。
配置 UIImagePickerController
1.实现图片选择
UIImagePickerController的配置很简单,只有几个属性需要我们来设置,设置好属性和代理之后,只需要向其它页面一样将其present出来即可,简单的配置如下:
@objc func showImagePickerView() {guard UIImagePickerController.isSourceTypeAvailable(.photoLibrary) else { return }let imagePickerController = UIImagePickerController()imagePickerController.delegate = selfimagePickerController.sourceType = .photoLibraryimagePickerController.mediaTypes = ["public.image"]present(imagePickerController, animated: true, completion: nil)}// Delegate methodsfunc imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {if let selectedImage = info[.originalImage] as? UIImage {// 使用选中的图片}dismiss(animated: true, completion: nil)}func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {dismiss(animated: true, completion: nil)}
在上面的代码中,
1.设置了UIImagePickerController的sourceType类型为photoLibrary意味着着我们将从媒体库中选择资源。
2.而mediaTypes属性设置为["public.image"]以为着我们只读取图片资源。
3.接着配置了UIImagePickerController的代理并且让视图控制器遵循代理并实现
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any])
和
func imagePickerControllerDidCancel(_ picker: UIImagePickerController)
两个代理方法,在我们选择图片后可以从info中直接读取出我们选择的图片资源。
效果如下:

2.实现视频选择
想要选择视频媒体资源,我们只需要修改它的mediaTypes属性为["public.movie"],代码如下:
@objc func showImagePickerView() {guard UIImagePickerController.isSourceTypeAvailable(.photoLibrary) else { return }let imagePickerController = UIImagePickerController()imagePickerController.delegate = selfimagePickerController.sourceType = .photoLibraryimagePickerController.mediaTypes = ["public.movie"]present(imagePickerController, animated: true, completion: nil)}
// Delegate methodsfunc imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {if let mediaType = info[.mediaType] as? String {if mediaType == "public.image" {// 使用选中的图片if let selectedImage = info[.originalImage] as? UIImage {// 使用选中的图片}} else if mediaType == "public.movie" {// 使用选中的视频if let videoURL = info[.mediaURL] as? URL {// 使用选中的视频}}}dismiss(animated: true, completion: nil)}
效果如下:

这样列表中就只有视频资源了,当然如果想要两个类型都可以选择的话,那么就两个字符串都添加进去["public.movie","public.image"],毕竟这是一个[String]类型。
3.直接拍摄图片
如果想要修改媒体资源的来源,这时候则需要调整sourceType属性,设置为.camera。mediaTypes属性仍然为["public.image"],代码如下:
@objc func showImagePickerView() {guard UIImagePickerController.isSourceTypeAvailable(.photoLibrary) else { return }let imagePickerController = UIImagePickerController()imagePickerController.delegate = selfimagePickerController.sourceType = .cameraimagePickerController.mediaTypes = ["public.image"]present(imagePickerController, animated: true, completion: nil)}
效果如下:

会有一个系统为我们提供的拍照页面,并附带一个取消按钮。拍照完成后,它的图片也会通过代理方法传递到当前控制器。
4.直接拍摄视频
参考上面的例子,直接拍摄的视频我们需要保持sourceType属性仍然为.camera,而mediaTypes属性设置为["public.movie"],(如果两个都可以的话仍然是设置mediaTypes属性为["public.movie","public.image"])。
@objc func showImagePickerView() {guard UIImagePickerController.isSourceTypeAvailable(.photoLibrary) else { return }let imagePickerController = UIImagePickerController()imagePickerController.delegate = selfimagePickerController.sourceType = .cameraimagePickerController.mediaTypes = ["public.move"]present(imagePickerController, animated: true, completion: nil)}
效果如下:

5.编辑媒体资源
UIImagePickerController还有一个allowsEditing属性,默认为false,当设置为true时,意味着在我们选择一个媒体资源后,会进入一个资源的编辑页面,编辑完成之后才会进入代理方法,这时候我们除了通过originalImage获取图片之外还可以通过editedImage来获取编辑后的图片。
而视频资源都是通过mediaURL来获取。
@objc func showImagePickerView() {guard UIImagePickerController.isSourceTypeAvailable(.photoLibrary) else { return }let imagePickerController = UIImagePickerController()imagePickerController.delegate = selfimagePickerController.sourceType = .photoLibraryimagePickerController.allowsEditing = trueimagePickerController.mediaTypes = ["public.movie", "public.image"]present(imagePickerController, animated: true, completion: nil)}


6.限制最大视频时长
我们可以通过videoMaximumDuration属性来设置视频资源的最大时长,在上传视频资源时,通常都会有一个长度限制,videoMaximumDuration的默认值为10,意味着大于10秒的视频不会显示在我们的列表。
7.自定义相机样式
UIImagePickerController也为我们保留了一些可以自定义相机样式的空间。
通过设置showsCameraControls属性为false。隐藏系统为我们提供的相机页面样式。
@objc func showImagePickerView() {guard UIImagePickerController.isSourceTypeAvailable(.photoLibrary) else { return }let imagePickerController = UIImagePickerController()imagePickerController.delegate = selfimagePickerController.sourceType = .cameraimagePickerController.allowsEditing = trueimagePickerController.mediaTypes = ["public.movie", "public.image"]imagePickerController.showsCameraControls = falsepresent(imagePickerController, animated: true, completion: nil)}
效果如下:

看起来有一点奇怪,不过当我们把它的控制视图隐藏之后确实就是这样,之后我们就需要多个属性配合来自己来实现它的拍照和录像的UI,而拍照和录像的方法UIImagePickerController已经提供给我们了:
// 拍照
open func takePicture()
// 录像
open func startVideoCapture() -> Bool
// 停止录像
open func stopVideoCapture()
// 设置相机模式
open var cameraCaptureMode: UIImagePickerController.CameraCaptureMode
还可以通过cameraViewTransform属性来修改预览画面的位置,
通过cameraOverlayView属性来自定义我们的控制视图。
下面我们就来实现一个简单自定义拍照的UI,代码如下:
@objc func showImagePickerView() {let view = UIView(frame: CGRect(x: 0, y: self.view.bounds.size.height - 200, width: self.view.bounds.size.width, height: 200.0))let button = UIButton()button.setImage(UIImage(named: "dynamic_post_photo_camare"), for: .normal)button.layer.masksToBounds = truebutton.layer.cornerRadius = 30.0view.addSubview(button)button.snp.makeConstraints { make inmake.centerX.equalToSuperview()make.width.height.equalTo(60.0)make.top.equalToSuperview().offset(40.0)}button.addTarget(self, action: #selector(takePhoto), for: .touchUpInside)guard UIImagePickerController.isSourceTypeAvailable(.photoLibrary) else { return }let imagePickerController = UIImagePickerController()imagePickerController.delegate = selfimagePickerController.sourceType = .cameraimagePickerController.allowsEditing = trueimagePickerController.mediaTypes = ["public.movie", "public.image"]imagePickerController.showsCameraControls = falseimagePickerController.cameraViewTransform = CGAffineTransform(translationX: 0, y: 100.0)imagePickerController.cameraOverlayView = viewpresent(imagePickerController, animated: true, completion: nil)self.imagePickerController = imagePickerController}@objc func takePhoto() {self.imagePickerController?.takePicture()}
效果如下:

结语
通过这篇博客,我们深入探讨了 UIImagePickerController 的各种功能和实现方法。我们了解了如何选择和拍摄图片及视频,如何编辑媒体,如何限制视频的最大长度,以及如何自定义相机样式。这些功能为开发者提供了丰富的工具,帮助我们创建出更加直观和用户友好的应用。
UIImagePickerController 是一个强大而灵活的组件,能够满足大多数基础的媒体选择和拍摄需求。尽管如此,对于更复杂的场景,苹果也提供了 PHPickerViewController 和其他更高级的框架,供开发者进一步探索和使用。下一篇博客我们来探讨它。
希望通过这篇博客,你能够更加熟练地使用 UIImagePickerController,并在你的项目中实现更加丰富的媒体处理功能。如果你有任何疑问或需要进一步的帮助,欢迎在评论区留言,我们共同探讨进步!
相关文章:
iOS 系统提供的媒体资源选择器(UIImagePickerController)
简介 图片或者视频的选择功能几乎是每个APP必不可少的,UIImagePickerController 是 iOS 系统提供的一个方便的媒体选择器,允许用户从照片库中选择图片或视频,或者使用相机拍摄新照片和视频。 它的页面简单易用,代码稳定可靠&…...
电脑如何扩展硬盘分区?告别空间不足困扰
在数字化时代,电脑硬盘的存储空间显得愈发重要。随着个人文件、应用程序和系统更新的不断累积,原有的硬盘分区可能很快就会被填满。为了解决这个问题,扩展硬盘分区成为了一个非常实用的方法。那么,电脑如何扩展硬盘分区呢…...
论文阅读:Mammoth: Building math generalist models through hybrid instruction tuning
Mammoth: Building math generalist models through hybrid instruction tuning https://arxiv.org/pdf/2309.05653 MAmmoTH:通过混合指令调优构建数学通才模型 摘要 我们介绍了MAmmoTH,一系列特别为通用数学问题解决而设计的开源大型语言模型&#…...
什么样的双筒式防爆器把煤矿吸引?
什么样的双筒式防爆器把煤矿吸引?要有好的服务和态度,要用心去聆听客户的需求,去解决客户的疑虑,用诚信去赢得客户的信任。 150产品的技术特点 双筒式防爆器采用双罐结构,其水封水位观测直观、能够快速有效排污、操作…...
如何保证冰河AL0 400G 100W 的稳定运行?
要保证冰河 AL0 400G 100w 的稳定运行,可以考虑以下几点: 1. 适宜的工作环境:确保设备放置在通风良好、温度适宜的环境中。良好的散热条件有助于防止设备过热,因为过热可能会导致性能下降或故障。该设备采用纯铝合金外壳…...
剪画小程序:巴黎奥运会,从画面到声音!
在巴黎奥运会的赛场上,每一个瞬间都伴随着独特的声音。那是观众的欢呼,是运动员冲刺的呐喊,是国歌奏响的激昂旋律。 如今,通过剪画音频提取,我们能够将这些珍贵的声音从精彩的画面中分离出来,单独珍藏。 想…...
【leetcode详解】心算挑战: 一题搞懂涉及奇偶数问题的 “万金油” 思路(思路详解)
前记: 做了几日的leetcode每日一题,几乎全是十分钟结束战斗的【中等】题,今日杀出来个【简单】题,反倒开始难以想出很清楚的解题思路,反复调试修改才将题目逐渐考虑全面,看到了原本思路的漏洞,…...
【资料集】数据库设计说明书(Word原件提供)
2 数据库环境说明 3 数据库的命名规则 4 逻辑设计 5 物理设计 5.1 表汇总 5.2 表结构设计 6 数据规划 6.1 表空间设计 6.2 数据文件设计 6.3 表、索引分区设计 6.4 优化方法 7 安全性设计 7.1 防止用户直接操作数据库 7.2 用户帐号加密处理 7.3 角色与权限控制 8 数据库管理与维…...
MySQL 常用查询语句精粹
引言 MySQL 是一种广泛使用的开源关系型数据库管理系统,其强大的查询语言为用户提供了丰富的数据处理能力。掌握 MySQL 的常用查询语句对于数据库管理和数据分析至关重要。本文将介绍一些 MySQL 中的常用查询语句,并提供实际的示例。 基础查询 1. 选择…...
hive的内部表(MANAGED_TABLE)和外部表(EXTERNAL_TABLE)的区别
1.hive的表类型分为外部表和内部表 内部表和外部表的主要区别在于数据的存储方式。 外部表:外部表的存储在hdfs中,是我们指定的文件目录,当我们删除数据或者删除分区的时候不会将元数据删除,数据还会在hdfs目录中,我们…...
【AutoSar网络管理】验证ecu能够从RepeatMessage状态切换到ReadySleep
本专栏将为您提供: Autosar网络管理介绍,包括:状态迁移、状态行为、状态表现、切换条件、时间参数、消息类型等。DUT模拟节点介绍,包括:设计思路、代码展示、编写须知等。测试用例介绍,包括:测试内容、测试步骤、期望结果等。测试脚本介绍,包括:编写思路、代码展示、脚…...
js逻辑或(||)和且()
重点: JavaScript 中的逻辑运算符按照布尔逻辑进行计算,并且返回值是操作数本身 || ||:逻辑或,只要有一个表达式为真(truthy),整个表达式就为真 逻辑或 (||) 的行为: ||运算符可以用来连接两个…...
ElasticSearch入门(六)SpringBoot2
private String author; Field(name “word_count”, type FieldType.Integer) private Integer wordCount; /** Jackson日期时间序列化问题: Cannot deserialize value of type java.time.LocalDateTime from String “2020-06-04 15:07:54”: Failed to des…...
vue项目Nginx部署启动
1.vue打包 (1)package.json增加打包命令 "scripts": {"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js --host 10.16.14.110","start": "npm run dev","un…...
Duplicate class kotlin.collections.jdk8.CollectionsJDK8Kt found in modules。Android studio纯java代码报错
我使用java代码 构建项目,初始代码运行就会报错。我使用的是Android Studio Giraffe(Adroid-studio-2022.3.1.18-windows)。我在网上找的解决办法是删除重复的类,但这操作起来真的太麻烦了。 这是全部报错代码: Dupli…...
filebeat
1、作用 1、可以在本机收集日志2、也可以远程收集日志3、轻量级的日志收集系统,可以在非java环境运行。logstash是在jmv环境中运行,资源消耗很大,启动一个logstash要消耗500M左右的内存,filebeat只消耗10M左右的内存。收集nginx的…...
matlab y=sin(x) - 2/π*(x)函数绘制
[TOC](matlab ysin(x) - 2/π*(x)函数绘制) ysin(x) - 2/π*(x) clc; clear; close all; x_axis_length 10; y_axis_length 10; % 创建 x 值向量 x_positive linspace(0.1, 10, 1000); % 正半轴上的 x 值 x_negative linspace(-10, -0.1, 1000); % 负半轴上的 x 值% 计算…...
HyperDiffusion阅读
ICCV 2023 创新点 HyperDiffusion:一种用隐式神经场无条件生成建模的新方法。 HyperDiffusion直接对MLP权重进行操作,并生成新的神经隐式场。 HyperDiffusion是与维度无关的生成模型。可以对不同维度的数据用相同的训练方法来合成高保真示例。 局限性…...
分治思想 排序数组
题目 这是一道经典的关于分治思想的算法题,适合刚接触分治的小白。 . - 力扣(LeetCode) 思路 采用递归分治的思想,也就是快速排序的模拟,这里先确定每趟递归的作用: 在一个规定的区间内,随机…...
通用前端分页插件
/*** >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>* 分页组件* >>>>>>>>>>>>>>>>>>>…...
MongoDB GridFS中出现大小为0的文件记录是怎么回事
files集合有记录但chunks为空,最常见原因是文件写入中途失败,导致仅插入files文档而未写入任何chunks。为什么 files 集合里有记录但 chunks 为空?这是最常见原因:文件写入中途失败,导致只插入了 files 文档࿰…...
AUTOSAR Ethernet Stack深度解析,手把手实现SOME/IP序列化、DDS桥接与时间同步校准
第一章:AUTOSAR以太网协议栈架构概览AUTOSAR以太网协议栈是面向汽车电子域控制器与中央计算平台的关键通信基础设施,其设计严格遵循AUTOSAR Classic Platform规范(R21-11及后续版本),在保持与传统CAN/LIN协议栈统一配置…...
从进度到资源:7款适合PMO的项目集管理系统
本文将深入对比7大项目集管理系统:PingCode、Worktile、GanttPRO、奥博思、TAPD、Trello、氚云 在管理大型、跨部门的复杂项目时,PMO(项目管理办公室)常面临资源冲突、信息孤岛和进度失控的挑战。传统的单项目管理工具已难以承载组…...
嵌入式开发中段错误的成因分析与GDB调试实战
1. 嵌入式软件段错误概述段错误(Segmentation Fault)是嵌入式开发中最令人头疼的运行时错误之一。作为一名在嵌入式领域摸爬滚打多年的工程师,我处理过的段错误案例不下百例。每次遇到这种错误,就像在漆黑的迷宫里寻找出口&#x…...
VSG阻抗扫描实战:从建模仿真到扫频验证
VSG 扫频法 阻抗扫描 阻抗建模验证 正负序阻抗 持续 更新 迭代 新能源 变流器 逆变器 虚拟同步控制 VSG 复现 基于序阻抗的虚拟同步机同步频率谐振现象 可设置扫描范围、扫描点数 程序附带注释,每一行都能看懂 包括 vsg仿真模型,阻抗建模程序࿰…...
Lychee-Rerank与MySQL协同实战:构建智能内容检索系统
Lychee-Rerank与MySQL协同实战:构建智能内容检索系统 你是不是也遇到过这样的烦恼?在自己的博客或者内容平台上,辛辛苦苦写的文章,用户却搜不到。明明文章里提到了某个技术点,但用户用关键词一搜,要么搜出…...
python python-telegram-bot
# 聊聊Python-Telegram-Bot:一个让机器人活起来的工具 如果你曾经用过Telegram,可能会注意到上面有各种各样的机器人,有的能帮你查天气,有的能管理群组,还有的甚至能陪你聊天。这些机器人背后,很多时候都是…...
基于Vue的青年志愿者乡村服务管理系统[vue]-计算机毕业设计源码+LW文档
摘要:随着乡村振兴战略的深入实施,青年志愿者在乡村服务中的作用日益凸显。为了提高青年志愿者光明村乡村服务的管理效率和质量,本文设计并实现了一个基于Vue的青年志愿者乡村服务管理系统。本文详细阐述了系统的开发背景、相关技术、需求分析…...
三自由度机械臂自适应神经网络控制(径向基函数)Matlab代码
✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。👇 关注我领取海量matlab电子书和数学建模资料🍊个人信条:格物致知,完整Matl…...
一文读懂:智慧人才管理系统的核心功能与企业应用价值
企业人力资源管理正从传统事务性操作迈向智能化新阶段,智慧人才管理系统作为核心支撑工具,正逐步重构人才管理模式。 很多企业面临数据孤岛、流程繁琐、决策依赖经验等痛点,智慧人才管理系统通过一体化整合与 AI 技术应用,实现人才…...
