PhotoManager.swift 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. //
  2. // PhotoManager.swift
  3. // TSLiveWallpaper
  4. //
  5. // Created by 100Years on 2024/12/24.
  6. //
  7. import Photos
  8. import UIKit
  9. let PhotoManagerShared = PhotoManager.shared
  10. class PhotoManager {
  11. static let shared = PhotoManager()
  12. func saveImagesToUniqueAlbum(images: [UIImage], baseAlbumName: String, completion: @escaping (Bool, Error?) -> Void) {
  13. // 检查并请求权限
  14. PHPhotoLibrary.requestAuthorization { status in
  15. guard status == .authorized else {
  16. completion(false, NSError(domain: "PhotoLibrary", code: 1, userInfo: [NSLocalizedDescriptionKey: "未获得相册访问权限"]))
  17. return
  18. }
  19. // 获取所有相册名称
  20. let allAlbumNames = self.fetchAllAlbumNames()
  21. let uniqueAlbumName = self.generateUniqueAlbumName(baseName: baseAlbumName, existingNames: allAlbumNames)
  22. // 保存图片到生成的相册
  23. self.saveImagesToAlbum(images: images, albumName: uniqueAlbumName, completion: completion)
  24. }
  25. }
  26. // 获取所有相册名称
  27. private func fetchAllAlbumNames() -> [String] {
  28. var albumNames: [String] = []
  29. let userCollections = PHCollectionList.fetchTopLevelUserCollections(with: nil)
  30. userCollections.enumerateObjects { collection, _, _ in
  31. if let album = collection as? PHAssetCollection, let albumName = album.localizedTitle {
  32. albumNames.append(albumName)
  33. }
  34. }
  35. return albumNames
  36. }
  37. // 生成唯一的相册名称
  38. private func generateUniqueAlbumName(baseName: String, existingNames: [String]) -> String {
  39. var uniqueName = baseName
  40. var index = 1
  41. while existingNames.contains(uniqueName) {
  42. uniqueName = "\(baseName)-\(index)"
  43. index += 1
  44. }
  45. return uniqueName
  46. }
  47. // 保存图片到指定相册(之前提供的 saveImagesToAlbum 方法)
  48. private func saveImagesToAlbum(images: [UIImage], albumName: String, completion: @escaping (Bool, Error?) -> Void) {
  49. var albumPlaceholder: PHObjectPlaceholder?
  50. let fetchOptions = PHFetchOptions()
  51. fetchOptions.predicate = NSPredicate(format: "title = %@", albumName)
  52. let collection = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: fetchOptions)
  53. if let existingAlbum = collection.firstObject {
  54. saveImages(images: images, to: existingAlbum, completion: completion)
  55. } else {
  56. PHPhotoLibrary.shared().performChanges {
  57. let creationRequest = PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: albumName)
  58. albumPlaceholder = creationRequest.placeholderForCreatedAssetCollection
  59. } completionHandler: { success, error in
  60. guard success, let placeholder = albumPlaceholder else {
  61. completion(false, error)
  62. return
  63. }
  64. let fetchResult = PHAssetCollection.fetchAssetCollections(withLocalIdentifiers: [placeholder.localIdentifier], options: nil)
  65. if let newAlbum = fetchResult.firstObject {
  66. self.saveImages(images: images, to: newAlbum, completion: completion)
  67. } else {
  68. completion(false, NSError(domain: "PhotoLibrary", code: 2, userInfo: [NSLocalizedDescriptionKey: "创建相册失败"]))
  69. }
  70. }
  71. }
  72. }
  73. // 保存图片到指定相册
  74. private func saveImages(images: [UIImage], to album: PHAssetCollection, completion: @escaping (Bool, Error?) -> Void) {
  75. PHPhotoLibrary.shared().performChanges {
  76. let assetRequest = images.map { PHAssetChangeRequest.creationRequestForAsset(from: $0) }
  77. let assetPlaceholders = assetRequest.compactMap { $0.placeholderForCreatedAsset }
  78. guard !assetPlaceholders.isEmpty else { return }
  79. if let albumChangeRequest = PHAssetCollectionChangeRequest(for: album) {
  80. albumChangeRequest.addAssets(assetPlaceholders as NSArray)
  81. }
  82. } completionHandler: { success, error in
  83. completion(success, error)
  84. }
  85. }
  86. /// 保存图片到相册
  87. /// - Parameters:
  88. /// - image: 要保存的 UIImage
  89. /// - completion: 保存结果的回调,返回成功与否和错误信息
  90. func saveImageToAlbum(_ image: UIImage, completion: @escaping (Bool, Error?) -> Void) {
  91. // 检查相册权限
  92. PHPhotoLibrary.requestAuthorization { status in
  93. DispatchQueue.main.async {
  94. switch status {
  95. case .authorized:
  96. // 权限已授权,保存图片
  97. self.save(image: image, completion: completion)
  98. case .limited:
  99. // 在受限权限下保存图片
  100. self.save(image: image, completion: completion)
  101. case .denied, .restricted:
  102. // 权限被拒绝或受限
  103. completion(false, NSError(domain: "PhotoSaver", code: 1, userInfo: [NSLocalizedDescriptionKey: "Photo Library access is denied."]))
  104. case .notDetermined:
  105. // 不会进入这个分支,因为已经请求了权限
  106. completion(false, NSError(domain: "PhotoSaver", code: 2, userInfo: [NSLocalizedDescriptionKey: "Photo Library access not determined."]))
  107. @unknown default:
  108. completion(false, NSError(domain: "PhotoSaver", code: 3, userInfo: [NSLocalizedDescriptionKey: "Unknown authorization status."]))
  109. }
  110. }
  111. }
  112. }
  113. /// 保存图片到相册的具体实现
  114. private func save(image: UIImage, completion: @escaping (Bool, Error?) -> Void) {
  115. PHPhotoLibrary.shared().performChanges({
  116. PHAssetChangeRequest.creationRequestForAsset(from: image)
  117. }) { success, error in
  118. DispatchQueue.main.async {
  119. completion(success, error)
  120. }
  121. }
  122. }
  123. }