27

PJHubs-PhotosKit 开发总结(一)

 5 years ago
source link: http://www.cocoachina.com/ios/20181225/25916.html?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

> 这个组件做的实在是太久了,最近终于从一大堆事儿中慢慢的恢复过来了,继续肝!

## 前言

这次的组件开发换了个思路继续精进,也还是 `MVC` 的模式,前段时间自己非常纠结到底哪种模式才是“最佳”设计模式?翻阅了大量资料,后来在[ 这篇文章 ]( https://www.jianshu.com/p/33c7e2f3a613 )中得到了“救赎”,让我真正的从回归到从实际问题出发,而不是一昧的为了“用”而用,尤其是在昨天的迭代总结会上,android 同学“夸夸其谈”的列出了许多所谓的“优化点”,某些“优化点”在我看来却是十分的可笑,本来以为来了个大佬,现在看来却是个“大佬”。

从 11 月末开始就着手准备开发这一新组件,但因为刚好与三方、新版本迭代期、期末课设等各种因素导致组件开发一再延后。该组件利用了 `PhotosKit` 框架,完成了从系统相册读取并自定义相册的功能,设计稿如下;

![ 设计稿 ]( https://i.loli.net/2018/12/21/5c1c9bade7ff8.png )

## 思考

一开始看到设计图后,感觉并没有多少东西需要去做,玩好 `PhotosKit` 即可,经过了一段时间后,再三确认后,最终的产品效果是要对齐 `Instagram` 里的“照片浏览器”体验一致,截图如下所示:

![ Instagram 照片浏览器截图 ]( https://i.loli.net/2018/12/21/5c1c9d27849a2.png )

接着我就去玩了 `Instagram` ,越玩越感觉这是个“大坑”,如果要做到 100% 的交互相似,估计做完直接丢出去开源又会拉到一波 star,对 `Instagram` 的”照片浏览器“分析如下:

* 可以简单的进行上下拆分。上部分为”选中视图“,可以直接套 `UIImageView` ,下部分为“浏览视图”,可用 `UICollectionView`

* 当”浏览视图“进行“上滑”操作时,无论滑动多么快速都不会触发“选中视图”的连带“上滑”操作;

* 当用户从“浏览视图”的范围滑动到“选中视图”中时,也就是手指触摸区域到达“选中视图”区域,将触发“选中视图”的连带“上滑”操作。

* 当“选中视图”已经到顶时,用户从“浏览视图”进行”下拉“操作,直接触发“选中视图”的连带“下拉”操作。

以上是目前总结出 `Instagram` 的“照片浏览器”四大要点,后续的开发工作也围绕着这四点进行。

## 需求拆分

**思考** 环节明确了该组件的开发难点后,开始对需求进行拆分,细致工作量。前几天还冒出了一个“笑话”,组件都快开发完了,自己却不放心,多嘴再去沟通了一遍,发现原来最终的效果和目前所实现的差距有些大,不得不又反工重来。

经过一番调研,设定的耗时为:2天,包括前后端联调。整理出的需求大致如下:

Feature | UI | Power

--- | --- | ---

浏览相册 | `UITableView` | 0.5

浏览相册照片 | `UICollectionView` | 1

交互 | - | 1

## 实现

一开始在数据源的获取上就跪了,之前在读取系统相册资源这方面需求仅仅只是“获取”这一方面,并没有对交互有太多的要求,也就一直没有精进,这回需要对相册做一个自定义就跪在数据源的获取上了,构思后,觉得有必要拉出一层 `DataManager` ,虽然只是从系统中拉数据,但为了“高内聚、低耦合”的理念,应该降低“调用方”的使用成本。

挑出了一部分 `PhotosKit` 框架核心知识点列举如下:

* `PHObject``Photos` 的资源集合和集合列表的抽象父类;

* `PHAssetCollection` :一个相册;

* `PHCollectionList` :一个包含多个相册的集合;

* `PHFetchResult`

* 作为 `PHAsset` (Live Photo)、 `PHCollection``PHAssetCollection``PHCollectionList` 相关方法的返回结果对象;

* 内容可动态加载,并不是直接把某个相册中的内容直接全部遍历出来,而是当需要一部分内容后才会去照片库中获取,这可以在处理大量结果时提供一个最佳性能;

* 默认 **线程安全**

* 缓存规则个人看法是利用了 `LRU` ,但实际上是不是这么一回事有待考证。

### 读取所有所需相册

加了个关键词——“所需”, `PhotosKit` 框架提供了一套十分完整的获取不同类型相册 API,在 `PJAlbumDataManager` 中,我是这么做的:

Swift

/// 获取所有相册

private func allAlbumCollection() -> [PHAssetCollection] {

var collections = [PHAssetCollection]()

let smartAlbums = PHAssetCollection.fetchAssetCollections(with: .smartAlbum,

subtype: .any,

options: nil) as! PHFetchResult

let userAlbums = PHCollectionList.fetchTopLevelUserCollections(with: nil)

for album in [smartAlbums, userAlbums] {

for s_i in 0..

let collection = album[s_i] as! PHAssetCollection

let types: [PHAssetCollectionSubtype] = [.albumRegular, // 用户自己创建的相册

.smartAlbumPanoramas, // 全景

.smartAlbumScreenshots, // 屏幕截图

.smartAlbumUserLibrary, // 相机胶卷

.smartAlbumRecentlyAdded] // 最近添加

if types.contains(collection.assetCollectionSubtype) {

collections.append(collection)
}
}
}
return collections
}

从上文中列出来的核心知识点,明确了 `PHAssetCollection` 相当于是一个相册,我们需要拿到由相机拍摄的照片集 `.smartAlbum` 和用户自己创建的照片集 `fetchTopLevelUserCollections` ,注意,这包括了“获取相册权限”的应用自行创建的相册。

`album` `PHAssetResult ` 类型,且因未实现 `Sequence` 协议,而无法进行遍历,而采取了一个简单的做法,至于比较优雅的做法暂未实现。

### 获取相册封面

通过以上方法,我们就拿到了当前用户设备中的所有所需相册集合。那如何获取一个相册的封面以及其所包含的照片数呢?经过一番研究后发现 `PHAssetCollection` 中提供了获取并未提供“封面”这个属性,同时也没有提供单独的 API 去获取一个相册封面,但是通过一个比较尴尬的方法,即通过获取相册中的所有照片 API 去锁定第一张照片,直接作为封面


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK