import AVFoundation import UIKit class ImageCaptureManager: NSObject { static let shared = ImageCaptureManager() private var completion: ((UIImage?) -> Void)? private weak var presentingViewController: UIViewController? func captureImage(from viewController: UIViewController, completion: @escaping (UIImage?) -> Void) { self.completion = completion self.presentingViewController = viewController let status = AVCaptureDevice.authorizationStatus(for: .video) switch status { case .authorized: presentImagePicker() case .notDetermined: AVCaptureDevice.requestAccess(for: .video) { [weak self] granted in DispatchQueue.main.async { if granted { self?.presentImagePicker() } else { self?.completion?(nil) } } } default: completion(nil) } } private func presentImagePicker() { guard UIImagePickerController.isSourceTypeAvailable(.camera) else { completion?(nil) return } let picker = UIImagePickerController() picker.sourceType = .camera picker.allowsEditing = true picker.delegate = self // Present from the topmost view controller var topController = UIApplication.shared.windows.first(where: { $0.isKeyWindow })?.rootViewController while let presentedVC = topController?.presentedViewController { topController = presentedVC } topController?.present(picker, animated: true) } } extension ImageCaptureManager: UINavigationControllerDelegate, UIImagePickerControllerDelegate { func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { let image = info[.editedImage] as? UIImage ?? info[.originalImage] as? UIImage picker.dismiss(animated: true) { [weak self] in self?.completion?(image) self?.completion = nil } } func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { picker.dismiss(animated: true) { [weak self] in self?.completion?(nil) self?.completion = nil } } }