TSPhotoPickerManager.swift 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  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. imagePicker = UIImagePickerController()
  53. imagePicker.sourceType = .photoLibrary
  54. imagePicker.delegate = self
  55. imagePicker.mediaTypes = ["public.image"] // 只选择照片
  56. imagePicker.modalPresentationStyle = .overFullScreen
  57. // imagePicker.modalTransitionStyle = .crossDissolve
  58. if #available(iOS 13.0, *) {
  59. imagePicker.overrideUserInterfaceStyle = .dark
  60. }
  61. viewController?.present(imagePicker, animated: true, completion: nil)
  62. }
  63. /// 显示权限提示
  64. private func showPermissionAlert() {
  65. let alert = UIAlertController(
  66. title: "No photos permission".localized,
  67. message: "Please enable photo permission in settings to select photos".localized,
  68. preferredStyle: .alert
  69. )
  70. alert.addAction(UIAlertAction(title: "Cancel".localized, style: .cancel, handler: nil))
  71. alert.addAction(UIAlertAction(title: "Go to Settings".localized, style: .default) { _ in
  72. if let url = URL(string: UIApplication.openSettingsURLString) {
  73. UIApplication.shared.open(url, options: [:], completionHandler: nil)
  74. }
  75. })
  76. viewController?.present(alert, animated: true, completion: nil)
  77. }
  78. }
  79. // MARK: - UIImagePickerControllerDelegate & UINavigationControllerDelegate (iOS 14 以下)
  80. extension TSPhotoPickerManager: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
  81. func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
  82. // picker.dismiss(animated: true) {
  83. if let image = info[.originalImage] as? UIImage {
  84. self.completionHandler?(image,info[.phAsset] as? PHAsset )
  85. } else {
  86. self.completionHandler?(nil,nil)
  87. }
  88. // }
  89. if completionSizeHandler == nil {
  90. picker.dismiss(animated: true, completion: nil)
  91. }
  92. }
  93. func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
  94. self.completionHandler?(nil,nil)
  95. if completionSizeHandler == nil {
  96. picker.dismiss(animated: true, completion: nil)
  97. }
  98. }
  99. }
  100. extension TSPhotoPickerManager{
  101. // MARK: - Public Methods
  102. /// 打开照片选择器,单选一张照片
  103. func pickSinglePhoto(maxBitSize:Int, completion: @escaping (UIImage?,String?) -> Void) {
  104. self.completionSizeHandler = completion
  105. let maxmbSize = Int(Double(maxBitSize) / (1024 * 1024))
  106. pickSinglePhoto { [weak self] image,phAsset in
  107. guard let self = self else { return }
  108. // if let image = image,let phAsset = phAsset {
  109. // // 方法2:异步获取详细大小(不阻塞主线程)
  110. // TSPhotoSizeHelper.getImageFileSizeAsync(asset: phAsset) {[weak self] size in
  111. // guard let self = self else { return }
  112. //
  113. // let mbSize = Double(size) / (1024 * 1024)
  114. // print("精确大小: \(mbSize) MB,size = \(size)")
  115. // if size > maxBitSize {
  116. // self.completionSizeHandler?(nil,String(format: "Photo must be smaller than %dMB.".localized, maxmbSize))
  117. // }else{
  118. // self.completionSizeHandler?(image,nil)
  119. // self.completionSizeHandler = nil
  120. // imagePicker.dismiss(animated: true)
  121. // }
  122. // }
  123. // }else
  124. if let image = image {
  125. if image.isLargerThan(byteSize: maxBitSize) {
  126. self.completionSizeHandler?(nil,String(format: "Photo must be smaller than %dMB.".localized, maxmbSize))
  127. }else{
  128. self.completionSizeHandler?(image,nil)
  129. self.completionSizeHandler = nil
  130. imagePicker.dismiss(animated: true)
  131. }
  132. }else{
  133. self.completionSizeHandler?(nil,nil)
  134. imagePicker.dismiss(animated: true)
  135. }
  136. }
  137. }
  138. }