// // PQPhotoAlbumController.swift // PQSpeed // // Created by SanW on 2020/8/31. // Copyright © 2020 BytesFlow. All rights reserved. // import Photos import UIKit /// 相册集 open class PQPhotoAlbumController: PQBaseViewController { public var selectedHandle: ((_ selectedData: PQUploadModel?) -> Void)? // 选中/取消选中的回调 public var isTopShow: Bool = false // 是否显示在顶部 public var categoryH: CGFloat = cDefaultMargin * 26 // 相簿高度 public var albaumsData: [PQUploadModel] = Array.init() public let itemSize = CGSize(width: ((cScreenWidth - cDefaultMargin) / 3) * UIScreen.main.scale, height: ((cScreenWidth - cDefaultMargin) / 3) * UIScreen.main.scale) var catagerySelectedIndex: IndexPath = IndexPath(item: 0, section: 0) // 更多图库选择 lazy public var imageManager: PHCachingImageManager = { PHCachingImageManager() }() lazy public var albaumCollectionView: UICollectionView = { let layout = UICollectionViewFlowLayout() layout.sectionInset = UIEdgeInsets.zero layout.itemSize = CGSize(width: view.frame.width, height: cDefaultMargin * 8 ) layout.minimumLineSpacing = 0 layout.minimumInteritemSpacing = 0 let albaumCollectionView = UICollectionView(frame: CGRect(x: 0, y: isTopShow ? 0 : (albaumView.frame.height - categoryH), width: albaumView.frame.width, height: isTopShow ? 0 : categoryH - 300), collectionViewLayout: layout) albaumCollectionView.showsVerticalScrollIndicator = false albaumCollectionView.register(PQAssetCategoryCell.self, forCellWithReuseIdentifier: "PQAssetCategoryCell") albaumCollectionView.delegate = self albaumCollectionView.dataSource = self if #available(iOS 11.0, *) { albaumCollectionView.contentInsetAdjustmentBehavior = .never } else { automaticallyAdjustsScrollViewInsets = false } albaumCollectionView.backgroundColor = UIColor.white return albaumCollectionView }() lazy public var emptyRemindView: PQEmptyRemindView = { let remindView = PQEmptyRemindView(frame: albaumCollectionView.bounds) remindView.isHidden = true albaumCollectionView.addSubview(remindView) remindView.backgroundColor = PQBFConfig.shared.styleBackGroundColor remindView.fullRefreshBloc = { [weak self] _, _ in if self?.emptyRemindView.refreshBtn.currentTitle == "授予权限" { openAppSetting() } else if self?.emptyRemindView.refreshBtn.currentTitle == "刷新" { self?.albaumsData.removeAll() self?.loadPhotoData() } } remindView.remindLab.textColor = UIColor.hexColor(hexadecimal: "#999999") remindView.refreshBtn.setTitle("授予权限", for: .normal) let anthorEmptyData = PQEmptyModel() anthorEmptyData.title = "挑选相册素材" anthorEmptyData.summary = "要挑选相册素材,请先授予相册使用权限" anthorEmptyData.emptyImage = "icon_authorError" anthorEmptyData.isRefreshHidden = false anthorEmptyData.refreshBgColor = UIColor.hexColor(hexadecimal: PQBFConfig.shared.styleColor.rawValue) remindView.emptyData = anthorEmptyData return remindView }() lazy public var albaumView: UIView = { let albaumView = UIView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height)) let ges = UITapGestureRecognizer(target: self, action: #selector(gesTagClick)) albaumView.addGestureRecognizer(ges) return albaumView }() open override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. view.backgroundColor = UIColor.init(red: 0, green: 0, blue: 0, alpha: 0.7) hiddenNavigation() loadPhotoData() } open override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) PHPhotoLibrary.shared().register(self) } open override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) PHPhotoLibrary.shared().unregisterChangeObserver(self) } } extension PQPhotoAlbumController { /// 修改view frame /// - Parameter frame: <#frame description#> /// - Returns: <#description#> public func updateViewFrame(frame: CGRect) { view.frame = frame view.isHidden = true view.addSubview(albaumView) view.addSubview(albaumCollectionView) } func loadPhotoData() { DispatchQueue.global().async { [weak self] in let allPhotos = PHAsset.fetchAssets(with: creaFetchOptions) if allPhotos.count > 0 { let tempData = PQUploadModel() tempData.title = "全部" tempData.categoryList = allPhotos self?.albaumsData.insert(tempData, at: 0) self?.updateItems(indexPath: IndexPath(item: 0, section: 0)) } DispatchQueue.main.async { [weak self] in self?.emptyRemindView.isHidden = allPhotos.count > 0 } let smartAlbums = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .albumRegular, options: nil) smartAlbums.enumerateObjects { [weak self] assCollection, _, _ in if assCollection.localizedTitle != "最近删除" { self?.convertCollection(collection: assCollection) } } let userCollections = PHCollectionList.fetchTopLevelUserCollections(with: nil) userCollections.enumerateObjects { [weak self] assCollection, index, point in BFLog(message: "userCollections == \(assCollection),index = \(index),point = \(point)") if assCollection is PHAssetCollection { if assCollection.localizedTitle != "最近删除" { self?.convertCollection(collection: assCollection as? PHAssetCollection) } } } } } // 转化处理获取到的相簿 public func convertCollection(collection: PHAssetCollection?) { if collection == nil { return } DispatchQueue.global().async { [weak self] in var options: PHFetchOptions = creaFetchOptions if collection?.localizedTitle == "最近项目" || collection?.localizedTitle == "最近添加" { options = modiFetchOptions } let assetsFetchResult = PHAsset.fetchAssets(in: collection!, options: options) if assetsFetchResult.count > 0 { let tempData = PQUploadModel() tempData.assetCollection = collection tempData.title = collection?.localizedTitle tempData.categoryList = assetsFetchResult if tempData.categoryList.count > 0 { if tempData.title == "视频" { self?.albaumsData.insert(tempData, at: 1) self?.updateItems(indexPath: IndexPath(item: 1, section: 0)) } else { self?.albaumsData.append(tempData) self?.updateItems(indexPath: IndexPath(item: (self?.albaumsData.count ?? 1) - 1, section: 0)) } } BFLog(message: "assetsFetchResult = \(assetsFetchResult)") } } } /// 更新数据源 /// - Parameter indexPath: <#indexPath description#> /// - Returns: <#description#> public func updateItems(indexPath _: IndexPath) { DispatchQueue.main.async { [weak self] in self?.albaumCollectionView.reloadData() // UIView.performWithoutAnimation {[weak self] in // self?.albaumCollectionView.performBatchUpdates({ // self?.albaumCollectionView.insertItems(at: [indexPath]) // }) {(isSuccess) in // // } // } } } /// 点击隐藏view /// - Returns: <#description#> @objc public func gesTagClick() { if selectedHandle != nil { selectedHandle!(nil) } albaumCollectionView.reloadData() dismissCategoryView() } @objc public func dismissCategoryView() { if isTopShow { UIView.animate(withDuration: 0.3, animations: { self.albaumCollectionView.frame = CGRect(x: 0, y: 0, width: cScreenWidth, height: 0) self.albaumView.alpha = 0 }) { _ in self.albaumView.isHidden = true self.view.isHidden = true } } else { albaumCollectionView.dismissViewAnimate { [weak self] _ in self?.view.isHidden = true } } } @objc public func showCategoryView() { if isTopShow { view.isHidden = false albaumView.isHidden = false albaumView.alpha = 0 // view.bringSubviewToFront(albaumView) UIView.animate(withDuration: 0.3, animations: { self.albaumCollectionView.frame = CGRect(x: 0, y: 0, width: cScreenWidth, height: self.categoryH) self.albaumView.alpha = 1 }) { _ in } albaumCollectionView.reloadData() } else { view.isHidden = false albaumCollectionView.showViewAnimate() } } } extension PQPhotoAlbumController: UICollectionViewDelegate, UICollectionViewDataSource, UIScrollViewDelegate { public func collectionView(_: UICollectionView, numberOfItemsInSection _: Int) -> Int { return albaumsData.count } public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = PQAssetCategoryCell.assetCategoryCell(collectionView: collectionView, indexPath: indexPath) let itemData = albaumsData[indexPath.item] let asset = itemData.categoryList.object(at: 0) cell.representedAssetIdentifier = asset.localIdentifier if itemData.image == nil { imageManager.requestImage(for: asset, targetSize: itemSize, contentMode: .aspectFill, options: nil) { image, info in if info?.keys.contains("PHImageResultIsDegradedKey") ?? false, "\(info?["PHImageResultIsDegradedKey"] ?? "0")" == "0", cell.representedAssetIdentifier == asset.localIdentifier { itemData.image = image cell.uploadData = itemData } } } else { cell.uploadData = itemData } cell.isSelected = indexPath == catagerySelectedIndex return cell } public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { if selectedHandle != nil { selectedHandle!(albaumsData[indexPath.item]) } catagerySelectedIndex = indexPath collectionView.reloadData() dismissCategoryView() } public func scrollViewDidScroll(_ scrollView: UIScrollView) { if (!isTopShow && (scrollView.contentOffset.y < -cDefaultMargin * 7)) || (isTopShow && scrollView.contentOffset.y > ((scrollView.contentSize.height - scrollView.frame.height) + cDefaultMargin * 10)) { if selectedHandle != nil { selectedHandle!(nil) } dismissCategoryView() } } } extension PQPhotoAlbumController: PHPhotoLibraryChangeObserver { public func photoLibraryDidChange(_: PHChange) { DispatchQueue.main.sync { // Check each of the three top-level fetches for changes. albaumsData.removeAll() loadPhotoData() } } }