TSPhotoPickerManager.swift 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. //
  2. // TSPhotoPickerManager.swift
  3. // AIEmoji
  4. //
  5. // Created by 100Years on 2025/2/25.
  6. //
  7. import UIKit
  8. import PhotosUI
  9. class TSPhotoPickerManager: NSObject {
  10. // MARK: - Properties
  11. private weak var viewController: UIViewController?
  12. private var completionHandler: ((UIImage?,PHAsset?) -> Void)?
  13. private var completionSizeHandler: ((UIImage?,String?) -> Void)?
  14. private var imagePicker = UIImagePickerController()
  15. // MARK: - Initializers
  16. init(viewController: UIViewController) {
  17. self.viewController = viewController
  18. }
  19. // MARK: - Public Methods
  20. /// 打开照片选择器,单选一张照片
  21. func pickSinglePhoto(completion: @escaping (UIImage?,PHAsset?) -> Void) {
  22. self.completionHandler = completion
  23. // 检查相册权限
  24. checkPhotoLibraryPermission { [weak self] authorized in
  25. guard let self = self else { return }
  26. if authorized {
  27. self.openPhotoPicker()
  28. } else {
  29. self.showPermissionAlert()
  30. }
  31. }
  32. }
  33. // MARK: - Private Methods
  34. /// 检查相册权限
  35. private func checkPhotoLibraryPermission(completion: @escaping (Bool) -> Void) {
  36. let status = PHPhotoLibrary.authorizationStatus()
  37. switch status {
  38. case .authorized:
  39. completion(true)
  40. case .notDetermined:
  41. PHPhotoLibrary.requestAuthorization { newStatus in
  42. DispatchQueue.main.async {
  43. completion(newStatus == .authorized)
  44. }
  45. }
  46. default:
  47. completion(false)
  48. }
  49. }
  50. /// 打开照片选择器
  51. private func openPhotoPicker() {
  52. TSToastShared.showLoading(containerView: viewController?.view)
  53. imagePicker = UIImagePickerController()
  54. imagePicker.sourceType = .photoLibrary
  55. imagePicker.delegate = self
  56. imagePicker.mediaTypes = ["public.image"] // 只选择照片
  57. // imagePicker.modalPresentationStyle = .custom
  58. // imagePicker.modalTransitionStyle = .crossDissolve
  59. if #available(iOS 13.0, *) {
  60. imagePicker.overrideUserInterfaceStyle = .dark
  61. }
  62. viewController?.present(imagePicker, animated: true, completion: nil)
  63. }
  64. /// 显示权限提示
  65. private func showPermissionAlert() {
  66. let alert = UIAlertController(
  67. title: "No photos permission".localized,
  68. message: "Please enable photo permission in settings to select photos".localized,
  69. preferredStyle: .alert
  70. )
  71. alert.addAction(UIAlertAction(title: "Cancel".localized, style: .cancel, handler: nil))
  72. alert.addAction(UIAlertAction(title: "Go to Settings".localized, style: .default) { _ in
  73. if let url = URL(string: UIApplication.openSettingsURLString) {
  74. UIApplication.shared.open(url, options: [:], completionHandler: nil)
  75. }
  76. })
  77. viewController?.present(alert, animated: true, completion: nil)
  78. }
  79. deinit {
  80. debugPrint("♻️♻️♻️ TSPhotoPickerManager -> TSPhotoPickerManager deinit ♻️♻️♻️")
  81. }
  82. }
  83. // MARK: - UIImagePickerControllerDelegate & UINavigationControllerDelegate (iOS 14 以下)
  84. extension TSPhotoPickerManager: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
  85. func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
  86. TSToastShared.hideLoading()
  87. // picker.dismiss(animated: true) {
  88. if let image = info[.originalImage] as? UIImage {
  89. self.completionHandler?(image,info[.phAsset] as? PHAsset )
  90. } else {
  91. self.completionHandler?(nil,nil)
  92. }
  93. // }
  94. if completionSizeHandler == nil {
  95. picker.dismiss(animated: true, completion: nil)
  96. }
  97. }
  98. func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
  99. TSToastShared.hideLoading()
  100. // self.completionHandler?(nil,nil)
  101. // if completionSizeHandler == nil {
  102. picker.dismiss(animated: true, completion: nil)
  103. // }
  104. }
  105. }
  106. extension TSPhotoPickerManager{
  107. func pickCustomSinglePhoto(completion: @escaping (UIImage?,String?) -> Void) {
  108. self.completionSizeHandler = completion
  109. pickSinglePhoto { [weak self] image,phAsset in
  110. guard let self = self else { return }
  111. self.completionSizeHandler?(image,nil)
  112. self.completionSizeHandler = nil
  113. }
  114. }
  115. // MARK: - Public Methods
  116. /// 打开照片选择器,单选一张照片
  117. func pickSinglePhoto(maxBitSize:Int, completion: @escaping (UIImage?,String?) -> Void) {
  118. self.completionSizeHandler = completion
  119. let maxmbSize = Int(Double(maxBitSize) / (1024 * 1024))
  120. pickSinglePhoto { [weak self] image,phAsset in
  121. guard let self = self else { return }
  122. if let image = image,let phAsset = phAsset {
  123. // 方法2:异步获取详细大小(不阻塞主线程)
  124. TSPhotoSizeHelper.getImageFileSizeAsync(asset: phAsset) {[weak self] size in
  125. guard let self = self else { return }
  126. let mbSize = Double(size) / (1024 * 1024)
  127. print("精确大小: \(mbSize) MB,size = \(size)")
  128. if size > maxBitSize {
  129. self.completionSizeHandler?(nil,String(format: "Photo must be smaller than %dMB.".localized, maxmbSize))
  130. }else{
  131. self.completionSizeHandler?(image,nil)
  132. self.completionSizeHandler = nil
  133. // imagePicker.dismiss(animated: true)
  134. }
  135. }
  136. }else{
  137. if let image = image {
  138. if image.isLargerThan(byteSize: maxBitSize) {
  139. self.completionSizeHandler?(nil,String(format: "Photo must be smaller than %dMB.".localized, maxmbSize))
  140. }else{
  141. self.completionSizeHandler?(image,nil)
  142. self.completionSizeHandler = nil
  143. // imagePicker.dismiss(animated: true)
  144. }
  145. }else{
  146. self.completionSizeHandler?(nil,nil)
  147. // imagePicker.dismiss(animated: true)
  148. }
  149. }
  150. }
  151. }
  152. func dismissPageVC(){
  153. self.imagePicker.view.isHidden = true
  154. self.imagePicker.dismiss(animated: true)
  155. }
  156. }