Photos框架 - 自定义媒体资源选择器(数据部分)
Photos框架 - 自定义媒体选择器(UI列表)
引言
我们已经实现了媒体资源的列表选择以及媒体资源的大图预览功能,但通常一个完整的媒体选择工具还需要附带一个可以选择指定相册资源的功能。毕竟,有时我们会对自己的相册进行分类,以便更方便地管理和查找。在这篇博客中,我们将探讨如何使用Photos框架来自定义相册列表,让用户可以更加灵活地选择和管理他们的媒体资源。
数据处理
那我们首先来处理数据部分,首先我们需要获取相册列表数据来构建一个相册资料的数据模型,里面应该包含封面资源,标题,以及所属相册的资源数量。
数据模型如下:
import UIKit
import Photos
class PHMediaAlbumModel: NSObject {
/// 相册
var assetCollection:PHAssetCollection?
/// 标识
var identifier:String?
/// 标题
var title:String? {
get {
assetCollection?.localizedTitle
}
}
/// 封面资源
var asset:PHAsset?
/// 资源数量
var count:Int = 0
}
然后为PHMediaManager添加获取相册列表的方法:
/// 相册列表
var albums: [PHMediaAlbumModel] = []
/// 获取相册资源
/// - Parameters:
/// - completion: 回调
func fetchLocalAlbums(completion: @escaping ([PHMediaAlbumModel]) -> Void) {
self.albums.removeAll()
let smartAlbums = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .any, options: nil)
smartAlbums.enumerateObjects { (collection, index, stop) in
let model = PHMediaAlbumModel()
model.assetCollection = collection
model.identifier = collection.localIdentifier
self.albums.append(model)
}
let fetchResult = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: nil)
fetchResult.enumerateObjects { collection, index, stop in
let model = PHMediaAlbumModel()
model.assetCollection = collection
model.identifier = collection.localIdentifier
self.albums.append(model)
}
for album in self.albums {
self.fetchAlbumCover(album: album.assetCollection!) { asset in
album.asset = asset
}
self.fetchAlbumCount(album: album.assetCollection!) { count in
album.count = count
}
}
completion(self.albums)
}
使用PHAssetCollection.fetchAssetCollections(with:subtype:options:)传递第一个参数为.album获取所有相册。subtype
参数指定相册的子类型(例如 .any
),options
参数可以用来指定额外的选项(在这个例子中为 nil
)。
使用相同的方法传递第一个参数.smartAlbum为获取所有智能相册。
定义两个私有方法用来获取相册的封面媒体资源以及指定相册的资源个数。
/// 获取指定相册的封面
/// - Parameters:
/// - album: 相册
/// - completion: 回调
private func fetchAlbumCover(album: PHAssetCollection, completion: @escaping (PHAsset?) -> Void) {
let options = PHFetchOptions()
options.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
options.fetchLimit = 1
let fetchResult = PHAsset.fetchAssets(in: album, options: options)
completion(fetchResult.firstObject)
}
/// 获取指定相册的资源个数
/// - Parameters:
/// - album: 相册
/// - completion: 回调
private func fetchAlbumCount(album: PHAssetCollection, completion: @escaping (Int) -> Void) {
let options = PHFetchOptions()
let fetchResult = PHAsset.fetchAssets(in: album, options: options)
completion(fetchResult.count)
}
调整fetchLocalMedias方法添加指定相册的参数,修改后代码如下:
/// 获取相册媒体资源
/// - Parameters:
/// - album: 相册
/// - completion: 回调
func fetchLocalMedias(album:PHMediaAlbumModel? = nil,completion: @escaping ([PHMediaModel]) -> Void) {
self.fetchLocalMedias(album:album,type: config.mediaType, completion: completion)
}
/// 获取本地所有媒体资源
/// - Parameters:
/// - album: 相册
/// - type: 类型
/// - completion: 回调
private func fetchLocalMedias(album:PHMediaAlbumModel? = nil,type: PHMediaType, completion: @escaping ([PHMediaModel]) -> Void) {
let options = PHFetchOptions()
.....
if let album = album {
fetchResult = PHAsset.fetchAssets(in: album.assetCollection!, options: options)
} else {
fetchResult = PHAsset.fetchAssets(with: options)
}
var assets = [PHMediaModel]()
....
self.displayMediaModels = assets
completion(assets)
}
UI实现
相册列表
首先来创建一个基础的列表UI,代码如下:
class PHMediaAlbumViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
/// 列表
let tableView = UITableView(frame: .zero, style: .plain)
/// 媒体资源管理类
var mediaManager:PHMediaManager!
/// 选择相册的回调
var selectAlbumBlock:((_ album:PHMediaAlbumModel)->Void)?
override func viewDidLoad() {
super.viewDidLoad()
setupView()
setLayout()
requestData()
}
func setupView() {
self.view.addSubview(tableView)
tableView.delegate = self
tableView.dataSource = self
tableView.separatorStyle = .none
tableView.register(PHMediaAlbumCell.self, forCellReuseIdentifier: "PHMediaAlbumCell")
}
func setLayout() {
tableView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
}
func requestData() {
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return mediaManager.albums.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "PHMediaAlbumCell", for: indexPath) as! PHMediaAlbumCell
cell.selectionStyle = .none
let album = mediaManager.albums[indexPath.row]
cell.renderData(albumModel: album, mediaManager: mediaManager)
return cell
}
}
调用PHMediaManager中我们新定义的fetchLocalAlbums方法来获取相册数据渲染列表:
func requestData() {
mediaManager.fetchLocalAlbums { [weak self] albums in
self?.tableView.reloadData()
}
}
实现点击事件,调用block代码将选择的相册数据回传到媒体资源列表:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let album = mediaManager.albums[indexPath.row]
if let block = selectAlbumBlock {
block(album)
}
}
显示相册
修改PHMediaPickerViewController的标题为按钮,并添加事件用来显示和隐藏相册列表:
navigationBar.titleButtonTouchBlock = { [weak self] in
if self?.mediaAlbumViewController != nil {
self?.mediaAlbumViewController?.view.removeFromSuperview()
self?.mediaAlbumViewController = nil
} else {
self?.showMediaAlbumViewController()
}
}
显示相册代码如下:
/// 显示相册列表
func showMediaAlbumViewController() {
mediaAlbumViewController = PHMediaAlbumViewController()
mediaAlbumViewController?.mediaManager = mediaManager
self.view.addSubview(mediaAlbumViewController!.view)
mediaAlbumViewController?.view.snp.makeConstraints { make in
make.top.equalTo(cs_navigationBarHeight)
make.leading.trailing.bottom.equalToSuperview()
}
mediaAlbumViewController?.selectAlbumBlock = {[weak self] album in
guard let self = self else { return }
self.navigationBar.title = album.title
self.mediaAlbumViewController?.view.removeFromSuperview()
self.mediaAlbumViewController = nil
self.fetchMediaData(album: album)
}
}
调用获取指定相册媒体资源的方法刷新列表:
/// 获取指定相册的媒体资源
func fetchMediaData(album:PHMediaAlbumModel) {
mediaManager.fetchLocalMedias(album: album) {[weak self] (mediaModels) in
guard let self = self else { return }
DispatchQueue.main.async {
self.collectionView.reloadData()
}
}
}
效果如下:
结语
通过本篇博客,我们已经了解了如何使用 Photos 框架来自定义媒体选择器,并获取相册的标题、封面和资源总数。然而,为了提升用户体验,我们还可以进一步优化显示效果。例如,通过过滤掉没有资源的相册,我们可以避免展示空相册,从而简化用户的选择过程。此外,还可以通过优化相册的显示效果,使用户能够更加直观和便捷地浏览和选择他们的媒体资源。希望这些技巧能够帮助你构建一个更高效、用户友好的媒体选择工具。
标签:album,completion,自定义,相册,self,options,Photos,let,选择器 From: https://blog.csdn.net/weixin_39339407/article/details/140814267