Created
October 23, 2020 20:58
-
-
Save rorodriguez116/018a13c1b496589531775b1cca0c309d to your computer and use it in GitHub Desktop.
PhotoCaptureProcessor implemented AVCapturePhotoCaptureDelegate
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Photos | |
class PhotoCaptureProcessor: NSObject { | |
lazy var context = CIContext() | |
private(set) var requestedPhotoSettings: AVCapturePhotoSettings | |
private let willCapturePhotoAnimation: () -> Void | |
private let completionHandler: (PhotoCaptureProcessor) -> Void | |
private let photoProcessingHandler: (Bool) -> Void | |
// The actual captured photo's data | |
var photoData: Data? | |
// The maximum time lapse before telling UI to show a spinner | |
private var maxPhotoProcessingTime: CMTime? | |
// Init takes multiple closures to be called in each step of the photco capture process | |
init(with requestedPhotoSettings: AVCapturePhotoSettings, willCapturePhotoAnimation: @escaping () -> Void, completionHandler: @escaping (PhotoCaptureProcessor) -> Void, photoProcessingHandler: @escaping (Bool) -> Void) { | |
self.requestedPhotoSettings = requestedPhotoSettings | |
self.willCapturePhotoAnimation = willCapturePhotoAnimation | |
self.completionHandler = completionHandler | |
self.photoProcessingHandler = photoProcessingHandler | |
} | |
} | |
extension PhotoCaptureProcessor: AVCapturePhotoCaptureDelegate { | |
// This extension adopts AVCapturePhotoCaptureDelegate protocol methods. | |
/// - Tag: WillBeginCapture | |
func photoOutput(_ output: AVCapturePhotoOutput, willBeginCaptureFor resolvedSettings: AVCaptureResolvedPhotoSettings) { | |
maxPhotoProcessingTime = resolvedSettings.photoProcessingTimeRange.start + resolvedSettings.photoProcessingTimeRange.duration | |
} | |
/// - Tag: WillCapturePhoto | |
func photoOutput(_ output: AVCapturePhotoOutput, willCapturePhotoFor resolvedSettings: AVCaptureResolvedPhotoSettings) { | |
DispatchQueue.main.async { | |
self.willCapturePhotoAnimation() | |
} | |
guard let maxPhotoProcessingTime = maxPhotoProcessingTime else { | |
return | |
} | |
// Show a spinner if processing time exceeds one second. | |
let oneSecond = CMTime(seconds: 2, preferredTimescale: 1) | |
if maxPhotoProcessingTime > oneSecond { | |
DispatchQueue.main.async { | |
self.photoProcessingHandler(true) | |
} | |
} | |
} | |
/// - Tag: DidFinishProcessingPhoto | |
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) { | |
DispatchQueue.main.async { | |
self.photoProcessingHandler(false) | |
} | |
if let error = error { | |
print("Error capturing photo: \(error)") | |
} else { | |
photoData = photo.fileDataRepresentation() | |
} | |
} | |
// MARK: Saves capture to photo library | |
func saveToPhotoLibrary(_ photoData: Data) { | |
PHPhotoLibrary.requestAuthorization { status in | |
if status == .authorized { | |
PHPhotoLibrary.shared().performChanges({ | |
let options = PHAssetResourceCreationOptions() | |
let creationRequest = PHAssetCreationRequest.forAsset() | |
options.uniformTypeIdentifier = self.requestedPhotoSettings.processedFileType.map { $0.rawValue } | |
creationRequest.addResource(with: .photo, data: photoData, options: options) | |
}, completionHandler: { _, error in | |
if let error = error { | |
print("Error occurred while saving photo to photo library: \(error)") | |
} | |
DispatchQueue.main.async { | |
self.completionHandler(self) | |
} | |
} | |
) | |
} else { | |
DispatchQueue.main.async { | |
self.completionHandler(self) | |
} | |
} | |
} | |
} | |
/// - Tag: DidFinishCapture | |
func photoOutput(_ output: AVCapturePhotoOutput, didFinishCaptureFor resolvedSettings: AVCaptureResolvedPhotoSettings, error: Error?) { | |
if let error = error { | |
print("Error capturing photo: \(error)") | |
DispatchQueue.main.async { | |
self.completionHandler(self) | |
} | |
return | |
} else { | |
guard let data = photoData else { | |
DispatchQueue.main.async { | |
self.completionHandler(self) | |
} | |
return | |
} | |
self.saveToPhotoLibrary(data) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment