Running an async task with a timeout

Could you elaborate a bit more, why you need the extra closure? Naively, since I am not familiar with this API, I would‘ve just used withTaskCancellationHandler like this:

extension PHImageManager {
    
    func requestImage(
        for asset: PHAsset,
        targetSize: CGSize,
        contentMode: PHImageContentMode,
        options: PHImageRequestOptions?
    ) async throws -> UIImage {
        let requestId = LockIsolated<PHImageRequestID?>(nil)
        return try await withTaskCancellationHandler {
           return try await withUnsafeThrowingContinuation { continuation in
               let newRequestId = requestImage(for: asset, targetSize: targetSize, contentMode: contentMode, options: options) { image, _ in
                   if let image {
                       continuation.resume(returning: image)
                   } else {
                       continuation.resume(throwing: CancellationError())
                   }
               }
               requestId.setValue(newRequestId)
            }
        } onCancel: {
            requestId.withValue { requestId in
                if let requestId {
                    cancelImageRequest(requestId)
                }
            }
        }
    }
}

LockIsolated is a helper from swift-concurrency-extras but I‘d imagine you could use Mutex instead, when it is released.

Edit: Please do not use this snippet, it is just for demonstration purposes. It will crash in some conditions because the requestImage closure can be called multiple times.