Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >iOS 开发实践:iOS照片API的那些坑

iOS 开发实践:iOS照片API的那些坑

作者头像
天天P图攻城狮
发布于 2018-07-09 10:54:26
发布于 2018-07-09 10:54:26
3K0
举报
文章被收录于专栏:天天P图攻城狮天天P图攻城狮

作者简介:keyishen(沈珂轶) 天天P图 iOS 工程师

在和图片打交道的那些日子里,遇到过不少图片相关的诡异问题。 在这里不会具体对照片API做介绍,而只会对其中的一些坑做一些总结。

1.不要完全相信系统API

当我们的程序有crash,但是通常我们的crash上报系统会上报自己app的crashlog,例如以下crashlog:

------------------------------------------------------------------------------------------------

由于是很偶现的crash,反复检查代码也没有发现什么疑点。还好在测试手机上后来发现了同一时间的另一个crashlog,如下:

------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------

原来在同一时间,系统负责AssetsLibrary功能的进程/System/Library/Frameworks/AssetsLibrary.framework/Support/assetsd crash了。从而导致了-[ALAsset valueForProperty:] 的调用始终卡在了那里。

系统的图片相关的操作主要是通过assetsd进程来实现的。

在对系统相册做一系列复杂操作后,有时会把系统assetsd进程搞挂,如果这时再回到app内调用Photos相关的API,就会出现异常现象,比如卡住,或者crash。这时可以看看手机里同一时刻之前是否有系统asset进程的crash堆栈。

我们目前的crash上报系统,往往无法定位到这张情况的问题。对于这种需要查看关联crash的情况就需要对系统的API也要合理地质疑。

2.不推荐自己写选图控件

对于选图没有太高要求的app,建议使用系统的选图控件UIImagePickerController,这样开发快捷便利,但是在我看来最大的优点在于这样做未来的维护成本会很小,尤其是可以在未来几乎第一时间享受到系统选图控件的新功能和新特性。

当然缺点是可调整的东西少,无法做个性化的定制,例如,不能控制UI,也很难做多图选择的扩展。

不过最不推荐的是在UIImagePickerController上面做UI的修改,这样虽然能够满足一时需求,但是却是为未来埋下了不少隐患,维护成本很高。

在iOS 10,如果用UIImagePickerController的话,还需要规避一个系统API会crash的坑。

在推出了3D touch之后,系统的UIImagePickerController在长按图片时会有偶现的crash。建议通过在UICollectionViewController的category里增加2个消息处理,来规避这个问题。具体增加的category如下:

3.支持的最低系统版本

苹果官方推荐始终只支持最新的2个大系统,就今天而言(2018.7)理论上我们应该只用支持iOS 10和iOS 11。然而国内的大环境,使得我们通常还需要从iOS 7,或者iOS 8开始支持。

对于图片类App来说,有一条很重要的分水岭,那就是iOS 8.1。

iOS 8开启了Photos.framework的新时代,而iOS 7及以下开发者只能使用AssetsLibrary的API。

然而可能是由于iOS 8推出匆忙,在iOS 8.0.x系统上,PHAsset的fetchAssetsWithMediaType: 和 fetchAssetsWithOptions:方法会返回iTunes同步的照片,以及iCloud照片流上的照片,所以如果你的照片被传到照片流上去后,通过这两个API返回的相册列表里会有两份相同的照片。

好在在iOS 8.1上苹果修改了这一API的行为,不再返回iTunes照片,以及照片流照片,使得Photos.framework从整个版本开始才真正意义上是可用的了。

对于小于iOS 8.1的系统都需要同时AssetsLibrary和Photos.framework两套图片API,对于非图片重度的app来说工作量不小。所以,推荐直接从iOS 9开始支持,如果不行的话,推荐至少从iOS 8.1开始支持(当然更合理的是从8.4开始支持,这样升级不到iOS 9的手机也有机会使用上)。

4.iCloud的坑

如果使用Photos.framework,那避不开的问题就是要支持iCloud上的照片。

为了推广苹果自己的iCloud的服务,并且拯救那些16GB手机的空间,苹果会将照片上传到iCloud,并且在本地只保存一份低清的照片。

4.1判断是否在iCloud上

我们APP在选图时需要判断本地是否存有原图。

Photos.framework提供了requestImageDataForAsset来获取图片的info。

Info的内容大致是这样的:

Printing description of info:

{

    PHImageResultDeliveredImageFormatKey = 9999;

    PHImageResultIsDegradedKey = 0;

    PHImageResultIsInCloudKey = 1;

    PHImageResultIsPlaceholderKey = 0;

    PHImageResultRequestIDKey = 54;

    PHImageResultWantedImageFormatKey = 9999;

}

理论上,info中的PHImageResultIsInCloudKey字段会告诉APP图片是否在iCloud上。

然而实际测试下来,该系统API有一个坑。在以上option的设置下,即使刚刚成功下载了这张图片,返回的info还是PHImageResultIsInCloudKey=1。

所以如果自己成功下载过图片后,还需要自己另外记忆下载的状态,在一定时间内,如果刚刚成功下载了图片,就应当要无视PHImageResultIsInCloudKey字段的状态,因为该字段的更新有滞后。

4.2判断iCloud API的卡死

在iOS 10系统上,还有一个新的坑,那就是用requestImageDataForAsset这个API会有一定概率出现永远不执行回调。

根据对在线用户的性能监控,我们发现这甚至是造成我们app卡顿的最大原因。通过对场景的重现我们发现,当这个API出现不回调bug时,各大主流app也几乎无一幸免,基本都卡在了那里。

所以为了解决这个问题,在调用requestImageDataForAsset的时候切忌放在主线程同步地做,并且需要给它一个超时时间,不让它无限制的执行。

5.正确获取缩略图

- (PHImageRequestID)requestImageForAsset:(PHAsset *)asset targetSize:(CGSize)targetSize contentMode:(PHImageContentMode)contentMode options:(nullable PHImageRequestOptions *)options resultHandler:(void (^)(UIImage *__nullable result, NSDictionary *__nullable info))resultHandler;

通过以上API,我们可以获取到各种尺寸的图片。虽然灵活性比之前AssetsLibrary的获取缩略图API高很多,但是方便程度差了不少,更多的灵活性带了的问题也不少。

这里涉及到一个系统API的坑requestImageForAsset这个API在某些targetSize下返回为空。

例如,在测试设备iPad Air(iOS 9.3.1)上,

如果targetSize=CGSizeMake(x, x),

当contentMode=PHImageContentModeAspectFill时,

且1<=x<=64 or 81<=x<=257时,

resultHandler返回的result image为nil。

当contentMode=PHImageContentModeAspectFit时,

且121<=x<=385时,

resultHandler返回的result image为nil。

在调用时需要多试试各个系统以及机型的适配性,尽量避开这些取值范围。

6.删除图片的API

在低于iOS 8的系统上,AssetsLibrary没有明确地提供删除图片的接口。

但事实上很多图片类APP通过修改图片的接口起到删除图片的作用,即通过ALAsset的接口直接删除图片。

但是当base sdk到了iOS 10之后,我们发现之前能用的接口现在在iOS 8.1及以上系统,会出现成功回调不执行的问题。

解决方法也很简单,就是直接使用Photos.framework提供的接口来删除图片:

附录:

https://objccn.io/issue-21-4/

http://stackoverflow.com/questions/25883005/avoiding-duplicates-when-getting-pictures-with-phasset

文章后记: 天天P图是由腾讯公司开发的业内领先的图像处理,相机美拍的APP。欢迎扫码或搜索关注我们的微信公众号:“天天P图攻城狮”,那上面将陆续公开分享我们的技术实践,期待一起交流学习!

加入我们: 天天P图技术团队长期招聘: (1) 图像处理算法工程师 (2) Android / iOS 开发工程师 期待对我们感兴趣或者有推荐的技术牛人加入我们(base 上海)!联系方式:ttpic_dev@qq.com

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-07-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 天天P图攻城狮 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
iOS中,系统相册的那些事
在手机APP日益增加的前提下,如何更好的提升用户的交互体验似乎成为衡量一个APP重要指标。上述的感悟源于实际工作的需求,就是在APP中添加一个更换用户头像的功能。 也许别人会认为这样一个小功能不算什么,但从用户交互角度考虑,这样一个功能的设计有一定学问,待我慢慢道来。 获取相册最直接的方式——UIImagePickerController 功能介绍:可直接显示分组的相处的列表,用户选择不同相册的照片后,可在委托方法中获得该图片对象; API提供三种数据源: UIImagePickerControllerSo
Jacklin
2018/05/15
1.5K0
iOS开发照片框架详解(二)-- PhotoKit
1 概要 在 iOS 8 出现之前,开发者只能使用 AssetsLibrary 框架来访问设备的照片库,这是一个有点跟不上 iOS 应用发展步伐以及代码设计原则但确实强大的框架。 iOS8 出现之后,苹果提供了一个名为 PhotoKit 的框架,一个可以让应用更好地与设备照片库对接的框架。PhotoKit 是一套比 AssetsLibrary 更完整也更高效的库,对资源的处理跟 AssetsLibrary 也有很大的不同。 2 PhotoKit组成介绍 PHAsset: 代表照片库中的一个资源,跟 ALAs
roc
2018/03/30
1.4K0
iOS开发照片框架详解(二)-- PhotoKit
番外特别篇之 为什么我不建议你直接使用UIImage传值?--从一个诡异的相册九图连读崩溃bug谈起
ios122
2018/01/02
1.8K0
番外特别篇之 为什么我不建议你直接使用UIImage传值?--从一个诡异的相册九图连读崩溃bug谈起
ios开发照片框架详解(一)-- AssetsLibrary
1 概要 在 iOS 设备中,照片和视频是相当重要的一部分。最近刚好在制作一个自定义的 iOS 图片选择器,顺便整理一下 iOS 中对照片框架的使用方法。在 iOS 8 出现之前,开发者只能使用 AssetsLibrary 框架来访问设备的照片库,这是一个有点跟不上 iOS 应用发展步伐以及代码设计原则但确实强大的框架,考虑到 iOS7 仍占有不少的渗透率,因此 AssetsLibrary 也是本文重点介绍的部分。而在 iOS8 出现之后,苹果提供了一个名为 PhotoKit 的框架,一个可以让应用更好地与
roc
2018/03/30
1.3K0
ios开发照片框架详解(一)-- AssetsLibrary
iOS14中的PHPicker
iOS 14 中系统新增了一个图片选择器 PHPicker,官方建议使用 PHPicker 来替代原有的 API 进行图片选择,下面我们来看看 PHPicker 的优点:
ios-lan
2020/10/16
3.7K1
iOS 图片选择打造专属于自己的 ImagePicker
从iOS8以后,Apple 就不再使用 AssetsLibrary 作为获取系统相册图片的方法了,转而在iOS8中推出了Photokit作为访问系统相册的库。官方对Photokit的概念解释为:
HelloWorld杰少
2022/08/04
1.5K0
iOS 图片选择打造专属于自己的 ImagePicker
Photos存储、获取、更改照片详解
前言: 相册保存到系统相册中,通常有三种办法: UIImageWriteToSavedPhotosAlbum() 方法保存 是使用 Photos 框架来实现。 ALAssetsLibrary 在iOS9.0之后就被标记为过时方法,苹果建议使用Photos框架代替 问:UIImageWriteToSavedPhotosAlbum()保存图片很简单,但为什么还要用Photos? 答: 1、Photos可以为相册相片做标识,方便保存后取出它们 2、Photos有同步操作,可以同时保存多张图片 3、可以存储
Dwyane
2018/05/22
2.2K0
IOS 获取设备本地音视频
当中assetsFetchResults存储了全部的图片信息。PHAssetMediaTypeImage为搜索图片的类型。相同的搜索其它类的能够依据
全栈程序员站长
2022/07/20
7520
酷我音乐iOS小组件适配开发实践
本文来自TME腾讯音乐娱乐-酷我音乐团队,迈腾大队长投稿,本文仅作为个人学习记录使用,也欢迎在许可协议范围内转载或使用,请尊重版权并且保留原文链接,谢谢您的理解合作. 如果您觉得本文章对您能有帮助,您可以使用关注此公众号,感谢支持.
QQ音乐技术团队
2023/12/15
1.3K0
酷我音乐iOS小组件适配开发实践
iOS基础开发实践:iMessage Extension浅析
作者简介:gennyxu(徐冬成) 天天P图 iOS 工程师 一)简介 iOS10新加入的基于iMessage的应用扩展,可以丰富发送消息的内容。(分享表情、图片、文字、视频、动态消息;一起完成任务或
天天P图攻城狮
2018/08/09
2.6K0
ios知识架构
学习ios开发,从哪儿学起?都要学哪些知识?如何才算掌握或精通ios开发?笔者根据自己多年的ios开发经验,给出一些体会,以便为立志成为ios开发精英的人员快速找到一条学习之路。本文是以最新上市的ios10 为依据的。
conanma
2021/11/04
6060
React Native iOS原生模块开发实战|教程|心得
尊重版权,未经授权不得转载 本文出自:贾鹏辉的技术博客(http://www.devio.org) 告诉大家一个好消息,为大家精心准备的React Native视频教程发布了,大家现可以看视频学React Native了。 前言 一直想写一下我在React Native原生模块封装方面的一些经验和心得,来分享给大家,但实在抽不开身,今天看了一下日历发现马上就春节了,所以就赶在春节之前将这篇博文写好并发布(其实是两篇:要看Android篇的点这里《React Native Android原生模块
CrazyCodeBoy
2018/05/07
2.2K0
React Native iOS原生模块开发实战|教程|心得
iOS开发之AssetsLibrary框架使用
    AssetsLibrary框架是专门用来操作相册相关资源的一个框架,其是iOS4到iOS9之间常使用的一个框架,在iOS9之后,系统系统了Photos框架代替了AssetsLibrary框架,但是AssetsLibrary框架依然可以使用,并且其结构和设计思路依然值得我们进行分析学习。
珲少
2018/09/20
1.2K0
iOS开发之AssetsLibrary框架使用
iOS开发中的这些权限,你搞懂了吗?
写在前面 APP开发避免不开系统权限的问题,如何在APP以更加友好的方式向用户展示系统权限,似乎也是开发过程中值得深思的一件事; 那如何提高APP获取iOS系统权限的通过率呢?有以下几种方式:1.在用户打开APP时就向用户请求权限;2.告知用户授权权限后能够获得好处之后,再向用户请求权限;3.在绝对必要的情况下才向用户请求权限,例如:用户访问照片库时请求访问系统相册权限;4.在展示系统权限的对话框前,先向用户显示自定义的对话框,若用户选择不允许,默认无操作,若用户选择允许,再展示系统对话框。 上述情况在开发
Jacklin
2018/05/15
1.2K0
iOS Crash 防护你看这个就够了 - 下篇
上篇 中讲到了 Crash 处理流程分为四个环节,也分析了 Crash 防护的方法,本章来讲下其余三个环节。
molier
2022/11/03
8160
iOS Crash 防护你看这个就够了 - 下篇
扫描iPhone所有照片,苹果自辩「保护儿童」引众怒!6000多人联名抵制
外媒爆出,苹果计划推出新版照片甄别系统(CSAM),通过扫描所有存储在 iCloud 上的照片,以找出符合虐待儿童、儿童色情内容的照片。
新智元
2021/08/25
6290
微信团队原创分享:iOS版微信的内存监控系统技术实践
FOOM(Foreground Out Of Memory),是指App在前台因消耗内存过多引起系统强杀。对用户而言,表现跟crash一样。Facebook早在2015年8月提出FOOM检测办法,大致原理是排除各种情况后,剩余的情况是FOOM,具体链接:https://code.facebook.com/posts/1146930688654547/reducing-fooms-in-the-facebook-ios-app/。
JackJiang
2018/08/29
2.1K1
iOS摄像头和相册-UIImagePickerController
本文参考自:http://blog.sina.com.cn/s/blog_7b9d64af0101cfd9.html
Cloudox
2021/11/23
8620
六天完成一个简单iOS App - 第五天
第五天任务 今天主要完成精华页面中cell内内容的处理。 cell高度的计算 cell中间内容的显示 精华模块的重构 查看图片 保存图片到相册 cell高度的计算 cell间距的设置,每个cell之间有10的间距,因为cell的重用机制,我们发现即使在tableView :didDeselectRowAtIndexPath方法中通过点击cell,减少cell的高度,当cell重新显示的时候还是会变回原来的高度,并且系统内部对cell进行了一些处理,已经在内部设置好cell的frame,所以我们通过重写cel
xx_Cc
2018/05/10
9350
iOS微信内存监控
本文介绍如何实现离线化的内存监控工具,用于 App 上线后发现内存问题。
WeTest质量开放平台团队
2018/03/01
3.6K0
iOS微信内存监控
相关推荐
iOS中,系统相册的那些事
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档