iOS开发进阶 - 基于PhotoKit的图片选择器

2023-05-16

移动端访问不佳,请访问我的个人博客

很早之前就用OC把代码写完了并用在项目中了,一直没时间整理,现在用swift重写一份,并且更加详细的来了解这个Photos框架,下面是我集合苹果官方文档和其他大神的博客写出的一篇关于Photos框架的介绍

老规矩先上效果图和Demo地址:

wcl

了解Photos框架

Photos是ios8出的一个新的图片选择框架,取代之前的AssetsLibrary框架,相比较AssetsLibrary框架Photos的用法更加灵活,发现在iOS9中AssetsLibrary已经被弃用了,并且也不支持livePhoto,iOS9上再使用AssetsLibrary框架时还有个严重的问题就是图片分辨率会变的很低,这篇文章主要讲解一下Photos的简单用法,用它做一个简单的图片选择器。

Photos中各个类的简单解释:

类名作用
PHAdjustmentData当用户编辑资源,照片与修改后的图像或视频数据保存在一个PHAdjustmentData对象中
PHAsset代表照片库中的一个资源实体,可以理解为一张照片,在打印的时候,可以清楚的看见里面包含了照片的时间、标题等信息
PHAssetChangeRequest使用PHAssetChangeRequest对象来创建、删除和修改相片库里面的PHAsset对象
PHAssetCollectionChangeRequest使用PHAssetCollectionChangeRequest对象来创建、删除和修改相片库里面的PHAssetCollection对象
PHAssetCreationRequest使用PHAssetCreationRequest对象构造一个新的照片或视频,并将其添加到照片库
PHAssetResource一个PHAssetResource对象表示在照片库中的照片或视频资源(也就是一个PHAsset对象)相关联的基础数据资源之一,使用PHAssetResourceManager类获取它
PHAssetResourceManagerPHAssetResourceManager对象提供了访问与照片资源相关的资源基础数据存储方法
PHChangePHChange对象来通知的照片库中的资源的一些变法,比如增加和删除
PHCollectionPHAssetCollection对象表示一组照片或视频资源。包括时刻和相册中可见照片应用,以及特殊的集合,如共享照片流。
PHCollectionListChangeRequest使用PHCollectionListChangeRequest对象在一个照片库中创建、删除或修改PHCollectionList对象。
PHContentEditingInputPHContentEditingInput对象描述资产用于编辑元数据
PHContentEditingOutputPHContentEditingOutput对象表示编辑照片资产的照片或视频内容的结果
PHFetchOptions获取资源时的检索参数,可以传 nil,即使用系统默认值
PHFetchResult通过PHFetchResult来获取照片实体的有序列表
PHImageManagerPHImageManager对象提供用于加载与PHAsset对象相关联的图像或视频数据的方法。使用这些方法来获取全尺寸照片资产或缩略图,或者检索AV Foundation对象播放,导出和操纵的视频资产。
PHLivePhoto用来获取LivePhoto实体
PHObject照片等实体的抽象类
PHPhotoLibraryPHPhotoLibrary对象表示用户的照片库整套资源和收藏的照片,包括存储在本地设备上在iCloud的照片对象。
PhotosTypes与Photos框架相关的类型的枚举

获取相册列表

获取相册列表可以需要用到一下类:

  • PHFetchOptions:对象检索的对象,可以对相册列表进行筛选
  • PHAssetCollection:图片集合的对象,筛选后获得的集合

下面是获取相册列表的代码片段:

    //MARK: 属性列表
    //全部相册的数组
    private(set) var photoAlbums    = [[String: PHFetchResult<PHAsset>]]()
    private(set) var selectPhotoArr = [PHAsset]()

    //是否同步请求图片
    public var isSynchronous: Bool = false {
        didSet{
            self.photoOption.isSynchronous = isSynchronous
        }
    }

    //MARK: 初始化方法
    override init() {
        super.init()
        //图片请求设置成快速获取
        self.photoOption.resizeMode   = .fast
        self.photoOption.deliveryMode = .opportunistic
        getPhotoAlbum()
    }

    /**
     开始获取获取相册列表
     */
    private func getPhotoAlbum() {
        //创建一个PHFetchOptions对象检索照片
        let options = PHFetchOptions()
        //通过创建时间来检索
        options.sortDescriptors = [NSSortDescriptor.init(key: photoCreationDate, ascending: false)]
        //通过数据类型来检索,这里为只检索照片
        options.predicate = NSPredicate.init(format: "mediaType in %@", [PHAssetMediaType.image.rawValue])
        //通过检索条件检索出符合检索条件的所有数据,也就是所有的照片
        let allResult = PHAsset.fetchAssets(with: options)
        //获取用户创建的相册
        let userResult = PHAssetCollection.fetchTopLevelUserCollections(with: nil)
        //获取智能相册
        let smartResult = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .albumRegular, options: nil)
        //将获取的相册加入到相册的数组中
        photoAlbums.append([WCLImagePickerBundle.localizedString(key: "全部照片"): allResult])

        userResult.enumerateObjects(options: .concurrent) { (collection, index, stop) in
            let assetcollection = collection as! PHAssetCollection
            //通过检索条件从assetcollection中检索出结果
            let assetResult = PHAsset.fetchAssets(in: assetcollection, options: options)
            if assetResult.count != 0 {
                self.photoAlbums.append([assetcollection.localizedTitle!:assetResult])
            }
        }

        smartResult.enumerateObjects(options: .concurrent) { (collection, index, stop) in
            //通过检索条件从assetcollection中检索出结果
            let assetResult = PHAsset.fetchAssets(in: collection, options: options)
            if assetResult.count != 0 {
                self.photoAlbums.append([collection.localizedTitle!:assetResult])
            }
        }
    }

获取某个相册的所有图片列表

需要用到的类:

  • PHFetchResult:对象检索的对象,可以对图片进行筛选
  • PHAsset:图片资源的对象,代表一个图片或者视频资源

下面贴代码片段:

    /**
     通过下标返回相册的PHFetchResult

     - parameter index: 选择相册的index

     - returns: 相册的PHFetchResult
     */
    public func getAblumResult(_ ablumIndex: Int) -> PHFetchResult<PHAsset>? {
        if let ablum = self.photoAlbums[wcl_safe: ablumIndex] {
            if let result = ablum.values.first {
                return result
            }
        }
        return nil
    }

上面代码中返回的result就代表选中的相册的图片列表

获取到单张图片的数据

通过上面获取到的相册的图片列表通过下标就能获得到图片对应的PHAsset,需要用到的类:

  • PHCachingImageManager:获取图片数据的Manager,也可缓存数据
  • PHImageRequestOptions:获取图片的一些选项配置,比如获取方式等等
  • PHAsset:图片资源的对象,代表一个图片或者视频资源

下面是代码片段:

    /**
     根据PHAsset获取photo

     - parameter ablumIndex:    相册的index
     - parameter alasset:       相册里图片的PHAsset
     - parameter photoSize:     图片的size
     - parameter resultHandler: 返回照片的回调
     */
    public func getPhoto(_ photoSize: CGSize, alasset: PHAsset?, resultHandler: ((UIImage?, [AnyHashable: Any]?) -> Void)?) {
        if alasset != nil {
            let scale = UIScreen.main.scale
            let photoScaleSize = CGSize(width: photoSize.width*scale, height: photoSize.height*scale)
            self.photoManage.requestImage(for: alasset!, targetSize: photoScaleSize, contentMode: .aspectFill, options: self.photoOption, resultHandler: { (image, infoDic) in
                if image != nil {
                    resultHandler?(image, infoDic)
                }else {
                //没获取到返回默认图片
                    let image_buffer = WCLImagePickerBundle.imageFromBundle("image-buffer")
                    resultHandler?(image_buffer, infoDic)
                }
            })
        }
    }

将图片存入相册

有时候我们需要将应用里的图片存到相册里面,一下是会用到的类:

  • PHPhotoLibrary:代表我们手机中的图片库,用它来操作图片库中的图片
  • PHAssetChangeRequest:资源操作的请求类,用来对资源进行操作

代码片段:

//执行变化
PHPhotoLibrary.shared().performChanges({
        //创建一个图片资源
        PHAssetChangeRequest.creationRequestForAsset(from: image)
    }, completionHandler: { (flag, error) in
        //执行结果回调
    })

总结

以上简单的讲解了一下Photos相关知识点和使用方法,更多的可以去官方文档上去查看。用Photos自己写了一个图片选择器,大家有兴趣的可以去看一下,有用的话可以star一下,写不不是很好,有什么错误可以指出来~最后谢谢大家的阅读。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

iOS开发进阶 - 基于PhotoKit的图片选择器 的相关文章

  • 安卓5.0以上7.0以下使用Termux

    参考 xff1a https zhuanlan zhihu com p 400507701 说明 xff1a Termux支持5 0以上的安卓系统 Termux7 3版本之后 xff0c 仅支持7 0以上的安卓系统 1 安装Termux 设
  • 关于DSP的CCS6.0平台下的工程搭建(完全可移植)

    本工程以CCS6 0下新建TMS320F28335工程为例 xff0c 其他系列处理器工程搭建类似 xff0c 参考本例即可 工程搭建用到的F2833x TI官方库文件 下载链接 也可直接参考笔者搭建好CCS6 0的工程 下载链接 所建工程
  • STM32Fxx JTAG/SWD复用功能重映射

    问题描述 xff1a 在实验室调车过程中 xff0c 遇到的一个问题 xff1a 为了每次下载程序方便 xff0c 队员们往往会把 Jlink 插在板子上 xff0c 可是在调车过程中发现 xff0c 有时程序会莫名死掉 xff0c 而同样
  • VS2012编译RTKLIB——GNSS定位开源库

    RTKLIB 开源库 有着强大的 GPS 数据实时和后处理功能 xff0c 由于 笔者的毕业设计中需要对GPS 载波相位观测量进行 RTK 解算 xff0c 故而 xff0c 对 RTKLIB 开源库进行了学习与研究 RTKLIB 提供了很
  • 51单片机串行口波特率计算

    1 工作方式介绍 xff1a 方式 0 xff1a 这种工作方式比较特殊 xff0c 与常见的微型计算机的串行口不同 xff0c 它又叫 同步移位寄存器输出方式 在这种方式下 xff0c 数据从 RXD 端串行输出或输入 xff0c 同步信
  • 解决HTTPS证书安全检测时提示 PCI DSS 不合规问题

    解决HTTPS证书安全检测时提示 PCI DSS 不合规问题 今天在进行HTTPS证书安全检测时 xff0c 提示PCI DSS不合规 经查询得知是因为SSL配置时启用了TLS1 0导致的 关于 PCI DSS 自2018年6月30日起 x
  • 数码管显示问题总结

    1 数码管显示原理 我们最常用的是七段式和八段式 LED 数码管 xff0c 八段比七段多了一个小数点 xff0c 其他的基本相同 所谓的八段就是指数码管里有八个小 LED 发光二极管 xff0c 通过控制不同的 LED 的亮灭来显示出不同
  • 多种方式登陆模块设计

    多种方式登陆模块设计 目录 多种方式登陆模块设计 目录参考了一些资料总结一下 1 使用 用户名邮箱手机号 密码 登陆2 第三方登陆 mob文档中还有以下描述 思考 参考了一些资料 知乎 第三方一键登录如何保证产品的唯一ID xff1f 开源
  • P1233 木棍加工

    题目描述 一堆木头棍子共有n根 xff0c 每根棍子的长度和宽度都是已知的 棍子可以被一台机器一个接一个地加工 机器处理一根棍子之前需要准备时间 准备时间是这样定义的 xff1a 第一根棍子的准备时间为1分钟 xff1b 如果刚处理完长度为
  • RUST 是 JavaScript 基建的未来

    这里写自定义目录标题 1 RUST 是 JavaScript 基建的未来1 1 Rust 是什么 1 2 Adoption1 3 从 JavaScript 到 Rust1 4 SWC1 5 Deno1 6 esbuild1 7 Rome1
  • VNC XRDP

    2个可以远程到linux上的远程桌面 xff0c 我都在我的raspi2上实现了 xff0c 这2个软件在我看来都差不多 xff0c 都可以满足我的要求 xff0c 只不过一个需要在windows上安装客户端VNC VIEWER xff0c
  • [Python学习]基础一: 循环

    34 if 语句可以嵌套 xff0c 但是不推荐 2 xff09 python 没有switch语句 3 xff09 循环语句 重复的执行某一个固定的动作或者任务 分类for while 4 xff09 for循环 for 变量 in 序列
  • springboot配置mysql数据库spring.datasource.url报错处理

    spring datasource url 61 jdbc mysql abc 3306 abcd useUnicode 61 true amp characterEncoding 61 utf8 很常规地配置了这个mysql的url后发现
  • 从jar包中读取文件的几种方式

    写在前面 本文会用到这篇文章 1 xff1a 从自身读取文件 1 1 xff1a 定义读取的文件 1 2 xff1a 读取代码 span class token annotation punctuation 64 SpringBootApp
  • Win10环境安装Anaconda(3-2021.05)+Tensorflow(2.6)

    Win10环境安装Anaconda 3 2021 05 43 Tensorflow 2 6 在学习机器学习的过程中会用到许多Python库 xff0c 例如tensorflow pandas等 xff0c 用到的时候单独去安装十分不方便 x
  • VIM中字符串的替换

    VIM中字符串的替换 字符串的替换 span class token number 1 span span class token function vim span 中可用 s 命令来替换字符串 xff0c 具体如下 xff1a s st
  • Golang依赖管理工具之go module(go1.11)

    大多数语言都会有包管理工具 xff0c 像Node有npm xff0c PHP有composer xff0c Java有Maven和Gradle 可是 xff0c Go语言一直缺乏一个官方的包管理 Dep被称为官方试验品official e
  • 一个linux驱动链表例子

    Free list初始化 span class token keyword struct span span class token class name list head span free list span class token
  • SAS学习笔记

    术语解释 Phy xff1a The term Phy is used in the standard with respect to the interface between a device and the service deliv
  • scsi命令的读写命令在哪里构建?

    drivers scsi sd c 中的sd setup read write cmnd函数里构建

随机推荐

  • linux查看磁盘的inquery data

    sg inq命令可以
  • SCSI任务优先级

    在SCSI命令参考手册中给出了三个优先级控制位 xff1a HEADSUP xff0c ORDWUP SIMPSUP xff0c 分别对应的优先级是HEAD OF QUEUE ORDERED SIMPLE HEAD OF QUEUE优先级的
  • 通过sg3_utils发送scsi cdb命令码

    sg raw 可以直接发送scsi命令 如sg raw r 1k dev sg0 12 00 00 00 60 00 是inquiry命令
  • 查看sas盘支持的所有命令

    sg raw r span class token number 1024 span dev sda a3 0c 00 00 00 00 00 00 04 00 00 00 或者 sg opcodes dev sda
  • [已解决]Ubuntu安装libssl-dev失败

    ygu 64 guyongqiangx span class token function sudo span span class token function apt get span span class token function
  • 安装ubuntu的时候注意事项

    安装的时候一定要选择上第三方更新 xff0c 并且不下载updates安装完毕后第一件事件就是 xff0c 搜索Software amp Updates 然后在Updates项目那里把自动检查更新更改为Never 通知我ubuntu有新版本
  • ubuntu16.04开机登录后一直蓝屏解决方法

    Ctrl 43 Alt 43 F4 xff0c 进入字符界面 xff0c 然后重新登录 xff0c 先输入用户名 xff0c 然后输入登录密码 xff0c 然后安装相应服务 xff0c 然后重置它 xff01 span class toke
  • 制作 macOS Mojave U盘启动盘/安装盘

    制作 macOS Mojave U盘启动盘 安装盘 下载macOS Mojave程序 去 App Store 下载好 macOS Mojave 安装程序 xff0c 先不要启动安装 下载完成后 xff0c 可在 Launchpad 中看到一
  • 自定义WSL的安装位置,别再装到C盘啦

    WSL Windows Subsystem for Linux 是win10的一项十分强大的功能 WSL让我们可以像使用普通的软件一样直接使用Linux的功能 配合微软的Windows Terminal xff0c 拥有比通常的虚拟机更方便
  • win10离线装linux子系统 运行ubuntu.exe失败闪退没反应

    解决过程 在新的系统版本下 xff0c lxrun等命令已经失效 xff0c 可利用wsl list verbose查看当前电脑上子系统信息 xff0c 成功之后如下图所示 xff1a 这里注意状态是running是因为已经配置好了 xff
  • SCSI Upper Layer 与LLD的联系——sd_probe

    SCSI UL和LLD的关系是driver和device的关系 内核中定义了device driver和device结构 xff0c 分别来抽象设备驱动和设备 这两个结构相当于所有设备驱动和设备的超类 UL代表的scsi driver和LL
  • sas控制器驱动之设备管理

    本文以2 6 32 68内核中的mpt2sas为例子 xff0c 介绍了sas驱动的设备管理 1 基本结构 内核中scsi的结构分三层 xff0c 此在网上已有大量资料 xff0c 不再赘述 本文在此基础上增加了mid layer的 tra
  • 结构体中char a[0]用法——柔性数组

    有如下定义 xff1a typedef struct char a char b 0 其中元素Char b 0 叫做柔性数组 xff0c 主要用于使结构体包含可变长字段 详细内容如下 xff1a 柔性数组 柔性数组结构成员 C99中 xff
  • dd命令中seek和skip的用法

    dd命令中seek和skip用法 xff0c 感兴趣的朋友可以参考下 假如有一个文件abc gz xff0c 大小为83456k xff0c 我想用dd命令实现如下备份 结果 xff1a 首先将备份分成三个部分 xff0c 第一部分为备份文
  • vscode常用集锦

    跳转 xff1a 跳转到第一行 xff1a 1 跳转到行尾 xff1a 1
  • yum install 失败 Failed to download metadata for repo ‘AppStream‘问题解决

    Centos8于2021年年底停止了服务 xff0c 大家再在使用yum源安装时候 xff0c 出现下面错误 错误 xff1a Failed to download metadata for repo AppStream Cannot pr
  • UEFI Drivers & UEFI Driver Model

    1 UEFI Drivers UEFI Drivers是UEFI Image的一种 xff0c UEFI Drivers与UEFI Applications的区别 xff1a Objects managed by UEFI based fi
  • 利用阿里云服务器自建DNS服务器

    好久没更新博客了 xff0c 突然想更新一下我最近的研究 国内DNS污染太严重了 xff0c 这就导致很多国内外没被墙的网站我们都打不开 xff0c 有时候就很麻烦 xff0c 所以最近我研究了一下AdGudrd Home xff0c 它是
  • Golang类型转换

    Go不会对数据进行隐式的类型转换 xff0c 只能手动去执行转换操作 strconv包提供了简单数据类型之间的类型转换功能 span class token keyword package span main span class toke
  • iOS开发进阶 - 基于PhotoKit的图片选择器

    移动端访问不佳 xff0c 请访问我的个人博客 很早之前就用OC把代码写完了并用在项目中了 xff0c 一直没时间整理 xff0c 现在用swift重写一份 xff0c 并且更加详细的来了解这个Photos框架 xff0c 下面是我集合苹果