PQPhotoAlbumController.swift 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. //
  2. // PQPhotoAlbumController.swift
  3. // PQSpeed
  4. //
  5. // Created by SanW on 2020/8/31.
  6. // Copyright © 2020 BytesFlow. All rights reserved.
  7. //
  8. import Photos
  9. import UIKit
  10. /// 相册集
  11. class PQPhotoAlbumController: PQBaseViewController {
  12. var selectedHandle: ((_ selectedData: PQUploadModel?) -> Void)? // 选中/取消选中的回调
  13. var isTopShow : Bool = false // 是否显示在顶部
  14. var categoryH: CGFloat = cDefaultMargin * 26 // 相簿高度
  15. var albaumsData: [PQUploadModel] = Array<PQUploadModel>.init()
  16. let itemSize = CGSize(width: ((cScreenWidth - cDefaultMargin) / 3) * UIScreen.main.scale, height: ((cScreenWidth - cDefaultMargin) / 3) * UIScreen.main.scale)
  17. var catagerySelectedIndex: IndexPath = IndexPath(item: 0, section: 0) // 更多图库选择
  18. lazy var imageManager: PHCachingImageManager = {
  19. PHCachingImageManager()
  20. }()
  21. lazy var albaumCollectionView: UICollectionView = {
  22. let layout = UICollectionViewFlowLayout()
  23. layout.sectionInset = UIEdgeInsets.zero
  24. layout.itemSize = CGSize(width: view.frame.width, height: cDefaultMargin * 8)
  25. layout.minimumLineSpacing = 0
  26. layout.minimumInteritemSpacing = 0
  27. let albaumCollectionView = UICollectionView(frame: CGRect(x: 0, y: isTopShow ? 0 : (albaumView.frame.height - categoryH), width: albaumView.frame.width, height: isTopShow ? 0 : categoryH), collectionViewLayout: layout)
  28. albaumCollectionView.showsVerticalScrollIndicator = false
  29. albaumCollectionView.register(PQAssetCategoryCell.self, forCellWithReuseIdentifier: "PQAssetCategoryCell")
  30. albaumCollectionView.delegate = self
  31. albaumCollectionView.dataSource = self
  32. if #available(iOS 11.0, *) {
  33. albaumCollectionView.contentInsetAdjustmentBehavior = .never
  34. } else {
  35. automaticallyAdjustsScrollViewInsets = false
  36. }
  37. albaumCollectionView.backgroundColor = UIColor.hexColor(hexadecimal: "#111111")
  38. return albaumCollectionView
  39. }()
  40. lazy var emptyRemindView: PQEmptyRemindView = {
  41. let emptyRemindView = PQEmptyRemindView(frame: albaumCollectionView.bounds)
  42. emptyRemindView.isHidden = true
  43. albaumCollectionView.addSubview(emptyRemindView)
  44. emptyRemindView.backgroundColor = UIColor.hexColor(hexadecimal: "#242424")
  45. emptyRemindView.fullRefreshBloc = { [weak self] _, _ in
  46. if emptyRemindView.refreshBtn.currentTitle == "授予权限" {
  47. openAppSetting()
  48. } else if emptyRemindView.refreshBtn.currentTitle == "刷新" {
  49. self?.albaumsData.removeAll()
  50. self?.loadPhotoData()
  51. }
  52. }
  53. emptyRemindView.remindLab.textColor = UIColor.hexColor(hexadecimal: "#999999")
  54. emptyRemindView.refreshBtn.setTitle("授予权限", for: .normal)
  55. let anthorEmptyData = PQEmptyModel()
  56. anthorEmptyData.title = "挑选相册素材"
  57. anthorEmptyData.summary = "要挑选相册素材,请先授予相册使用权限"
  58. anthorEmptyData.emptyImage = "icon_authorError"
  59. anthorEmptyData.isRefreshHidden = false
  60. emptyRemindView.emptyData = anthorEmptyData
  61. return emptyRemindView
  62. }()
  63. lazy var albaumView: UIView = {
  64. let albaumView = UIView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height))
  65. let ges = UITapGestureRecognizer(target: self, action: #selector(dismissCategoryView))
  66. albaumView.addGestureRecognizer(ges)
  67. return albaumView
  68. }()
  69. override func viewDidLoad() {
  70. super.viewDidLoad()
  71. // Do any additional setup after loading the view.
  72. view.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.6)
  73. hiddenNavigation()
  74. loadPhotoData()
  75. }
  76. override func viewWillAppear(_ animated: Bool) {
  77. super.viewWillAppear(animated)
  78. PHPhotoLibrary.shared().register(self)
  79. }
  80. override func viewWillDisappear(_ animated: Bool) {
  81. super.viewWillDisappear(animated)
  82. PHPhotoLibrary.shared().unregisterChangeObserver(self)
  83. }
  84. }
  85. extension PQPhotoAlbumController {
  86. /// 修改view frame
  87. /// - Parameter frame: <#frame description#>
  88. /// - Returns: <#description#>
  89. func updateViewFrame(frame: CGRect) {
  90. view.frame = frame
  91. view.isHidden = true
  92. view.addSubview(albaumView)
  93. view.addSubview(albaumCollectionView)
  94. }
  95. func loadPhotoData() {
  96. DispatchQueue.global().async { [weak self] in
  97. let allPhotos = PHAsset.fetchAssets(with: creaFetchOptions)
  98. if allPhotos.count > 0 {
  99. let tempData = PQUploadModel()
  100. tempData.title = "全部"
  101. tempData.categoryList = allPhotos
  102. self?.albaumsData.insert(tempData, at: 0)
  103. self?.updateItems(indexPath: IndexPath(item: 0, section: 0))
  104. }
  105. DispatchQueue.main.async { [weak self] in
  106. self?.emptyRemindView.isHidden = allPhotos.count > 0
  107. }
  108. let smartAlbums = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .albumRegular, options: nil)
  109. smartAlbums.enumerateObjects { [weak self] assCollection, _, _ in
  110. if assCollection.localizedTitle != "最近删除" {
  111. self?.convertCollection(collection: assCollection)
  112. }
  113. }
  114. let userCollections = PHCollectionList.fetchTopLevelUserCollections(with: nil)
  115. userCollections.enumerateObjects { [weak self] assCollection, index, point in
  116. BFLog(message: "userCollections == \(assCollection),index = \(index),point = \(point)")
  117. if assCollection is PHAssetCollection {
  118. if assCollection.localizedTitle != "最近删除" {
  119. self?.convertCollection(collection: assCollection as? PHAssetCollection)
  120. }
  121. }
  122. }
  123. }
  124. }
  125. // 转化处理获取到的相簿
  126. func convertCollection(collection: PHAssetCollection?) {
  127. if collection == nil {
  128. return
  129. }
  130. DispatchQueue.global().async { [weak self] in
  131. var options: PHFetchOptions = creaFetchOptions
  132. if collection?.localizedTitle == "最近项目" || collection?.localizedTitle == "最近添加" {
  133. options = modiFetchOptions
  134. }
  135. let assetsFetchResult = PHAsset.fetchAssets(in: collection!, options: options)
  136. if assetsFetchResult.count > 0 {
  137. let tempData = PQUploadModel()
  138. tempData.assetCollection = collection
  139. tempData.title = collection?.localizedTitle
  140. tempData.categoryList = assetsFetchResult
  141. if tempData.categoryList.count > 0 {
  142. if tempData.title == "视频" {
  143. self?.albaumsData.insert(tempData, at: 1)
  144. self?.updateItems(indexPath: IndexPath(item: 1, section: 0))
  145. } else {
  146. self?.albaumsData.append(tempData)
  147. self?.updateItems(indexPath: IndexPath(item: (self?.albaumsData.count ?? 1) - 1, section: 0))
  148. }
  149. }
  150. BFLog(message: "assetsFetchResult = \(assetsFetchResult)")
  151. }
  152. }
  153. }
  154. /// 更新数据源
  155. /// - Parameter indexPath: <#indexPath description#>
  156. /// - Returns: <#description#>
  157. func updateItems(indexPath _: IndexPath) {
  158. DispatchQueue.main.async { [weak self] in
  159. self?.albaumCollectionView.reloadData()
  160. // UIView.performWithoutAnimation {[weak self] in
  161. // self?.albaumCollectionView.performBatchUpdates({
  162. // self?.albaumCollectionView.insertItems(at: [indexPath])
  163. // }) {(isSuccess) in
  164. //
  165. // }
  166. // }
  167. }
  168. }
  169. @objc func dismissCategoryView() {
  170. if isTopShow {
  171. UIView.animate(withDuration: 0.3, animations: {
  172. self.albaumCollectionView.frame = CGRect(x: 0, y: 0, width: cScreenWidth, height: 0)
  173. self.albaumView.alpha = 0
  174. }) { _ in
  175. self.albaumView.isHidden = true
  176. self.view.isHidden = true
  177. }
  178. }else{
  179. albaumCollectionView.dismissViewAnimate { [weak self] _ in
  180. self?.view.isHidden = true
  181. }
  182. }
  183. }
  184. @objc func showCategoryView() {
  185. if isTopShow {
  186. view.isHidden = false
  187. albaumView.isHidden = false
  188. albaumView.alpha = 0
  189. // view.bringSubviewToFront(albaumView)
  190. UIView.animate(withDuration: 0.3, animations: {
  191. self.albaumCollectionView.frame = CGRect(x: 0, y: 0, width: cScreenWidth, height: self.categoryH)
  192. self.albaumView.alpha = 1
  193. }) { _ in
  194. }
  195. albaumCollectionView.reloadData()
  196. }else{
  197. view.isHidden = false
  198. albaumCollectionView.showViewAnimate()
  199. }
  200. }
  201. }
  202. extension PQPhotoAlbumController: UICollectionViewDelegate, UICollectionViewDataSource, UIScrollViewDelegate {
  203. func collectionView(_: UICollectionView, numberOfItemsInSection _: Int) -> Int {
  204. return albaumsData.count
  205. }
  206. func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
  207. let cell = PQAssetCategoryCell.assetCategoryCell(collectionView: collectionView, indexPath: indexPath)
  208. let itemData = albaumsData[indexPath.item]
  209. let asset = itemData.categoryList.object(at: 0)
  210. cell.representedAssetIdentifier = asset.localIdentifier
  211. if itemData.image == nil {
  212. imageManager.requestImage(for: asset, targetSize: itemSize, contentMode: .aspectFill, options: nil) { image, info in
  213. if info?.keys.contains("PHImageResultIsDegradedKey") ?? false, "\(info?["PHImageResultIsDegradedKey"] ?? "0")" == "0", cell.representedAssetIdentifier == asset.localIdentifier {
  214. itemData.image = image
  215. cell.uploadData = itemData
  216. }
  217. }
  218. } else {
  219. cell.uploadData = itemData
  220. }
  221. cell.isSelected = indexPath == catagerySelectedIndex
  222. return cell
  223. }
  224. func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
  225. if selectedHandle != nil {
  226. selectedHandle!(albaumsData[indexPath.item])
  227. }
  228. catagerySelectedIndex = indexPath
  229. collectionView.reloadData()
  230. dismissCategoryView()
  231. }
  232. func scrollViewDidScroll(_ scrollView: UIScrollView) {
  233. if (!isTopShow && (scrollView.contentOffset.y < -cDefaultMargin * 7)) || (isTopShow && scrollView.contentOffset.y > ((scrollView.contentSize.height - scrollView.frame.height) + cDefaultMargin * 10)) {
  234. dismissCategoryView()
  235. }
  236. }
  237. }
  238. extension PQPhotoAlbumController: PHPhotoLibraryChangeObserver {
  239. func photoLibraryDidChange(_: PHChange) {
  240. DispatchQueue.main.sync {
  241. // Check each of the three top-level fetches for changes.
  242. albaumsData.removeAll()
  243. loadPhotoData()
  244. }
  245. }
  246. }