Swift 使用async/await實現一句代碼獲取系統相冊照片和視頻
眾所周知,想要獲取系統相冊照片和視頻,也就是調起UIImagePickerController
,創建控制器、遵守代理、實現代理方法、彈出/關閉控制器,拿張照片都如此繁瑣。為了更快獲取系統相冊照片和視頻,於是封裝了一個系統相冊的工具類ImagePicker
,內部實現好代理和彈出/關閉的操作,方便自己平時調試。
- 🌰
ImagePicker
封裝的方法其一:打開相冊,通過閉包返回照片圖片:swift func getPhoto() { ImagePicker.openAlbumForImage { [weak self] result in guard let self = self else { return } switch result { case let .success(image): self.setupImage(image) case let .failure(pickError): pickError.log() } } }
這麼一看好像已經夠簡潔了,不過Swift
現在已經有async/await
的特性了,那是不是可以通過一句代碼就能獲取到圖片呢?
答案是肯定可以的啦。
從Swift中的async/await代碼實例詳解這篇文章中得知,可以通過withCheckedThrowingContinuation
將【基於閉包異步處理結果】轉換成【結構化併發同步處理結果】,實現一句代碼獲取系統相冊照片:
swift
func getPhoto() async {
let image: UIImage? = try? await ImagePicker.openAlbum()
imgView.image = image
}
這樣看上去就真的超簡潔了~
-
主要實現方式: ```swift // MARK: - Pick object handle private extension ImagePicker.Controller { // 以前的方式: // - 保存閉包,直至代理方法的調起,然後通過該閉包以返回結果 // - 外部調用:picker.pickObject() { result in ...... },通過閉包異步獲取結果 func pickObject(completion: @escaping ImagePicker.Completion
) { self.completion = completion } // 現在的方式: // - 通過
withCheckedThrowingContinuation
將【基於閉包異步處理結果】轉換成【結構化併發同步處理結果】 // - 外部調用:let object: T? = try? await picker.pickObject(),等待並同步獲取結果 func pickObject() async throws -> T { try await withCheckedThrowingContinuation { continuation in // 在以前的方式中這個閉包是給外部使用的,現在的方式修改成【內部使用】: // 外部先卡住函數,等待代理方法的調起,然後通過continuation
將結果返回給外部,實現同步處理。 pickObject() { result in continuation.resume(with: result) } } }// MARK: - UIImagePickerControllerDelegate // 用户選擇了照片/視頻 func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { // 1.獲取結果 let result: Result
do { result = .success(try T.fetchFromPicker(info)) } catch let pickError as ImagePicker.PickError { result = .failure(pickError) } catch { result = .failure(.other(error)) } // 2.返回結果 completion?(result) // 3.關閉控制器 dismiss(animated: true)
}
// 用户點擊了取消 func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { // 1.返回結果:用户點擊取消 completion?(.failure(.userCancel))
// 2.關閉控制器 dismiss(animated: true)
} } ```
-
通過泛型和重載的特性擴展一下,返回更多類型: ```swift // 相冊 -> 圖片 let image: UIImage? = try? await ImagePicker.openAlbum()
// 相冊 -> 二進制數據(圖片、GIF) let imageData: Data? = try? await ImagePicker.openAlbum()
// 相冊 -> 視頻路徑 let videoURL: URL? = try? await ImagePicker.openAlbum()
// 拍照 -> 圖片
let image: UIImage? = try? await ImagePicker.photograph()
``
PS:當然啦,肯定會有拿不到的情況,所有失敗的場景我都使用了
ImagePicker.PickError拋出,可通過
do {} catch {}`捕獲。
至此,封裝的ImagePicker
可以很方便地讓我獲取系統相冊的照片和視頻。
不過獲取相冊數據一般都會用第三方庫來做,我這個工具類只是更多的用來平時的調試,最主要是熟悉一下async/await
的特性。
OK,本文就到此為止,祝大家新年快樂~