Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NeverwinterMoon/b5d05e94ae09ccef9feec04a3c620195 to your computer and use it in GitHub Desktop.
Save NeverwinterMoon/b5d05e94ae09ccef9feec04a3c620195 to your computer and use it in GitHub Desktop.
How to use `PHImageManager#requestImage` with async/await in Swift.
import Photos
struct UnexpectedNilError: Error {}
extension PHImageManager {
func requestImage(
for asset: PHAsset,
targetSize: CGSize,
contentMode: PHImageContentMode,
options: PHImageRequestOptions?
) async throws -> UIImage {
options?.isSynchronous = false
var requestID: PHImageRequestID?
return try await withTaskCancellationHandler(
handler: { [requestID] in
guard let requestID = requestID else {
return
}
cancelImageRequest(requestID)
}
) {
try await withCheckedThrowingContinuation { continuation in
requestID = requestImage(
for: asset,
targetSize: targetSize,
contentMode: contentMode,
options: options
) { image, info in
if let error = info?[PHImageErrorKey] as? Error {
continuation.resume(throwing: error)
return
}
guard !(info?[PHImageCancelledKey] as? Bool ?? false) else {
continuation.resume(throwing: CancellationError())
return
}
// When degraded image is provided, the completion handler will be called again.
guard !(info?[PHImageResultIsDegradedKey] as? Bool ?? false) else {
return
}
guard let image = image else {
// This should in theory not happen.
continuation.resume(throwing: UnexpectedNilError())
return
}
// According to the docs, the image is guaranteed at this point.
continuation.resume(returning: image)
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment