Swift 使用async/await實現一句代碼獲取系統相冊照片和視頻

語言: CN / TW / HK

眾所周知,想要獲取系統相冊照片和視頻,也就是調起UIImagePickerController,創建控制器、遵守代理、實現代理方法、彈出/關閉控制器,拿張照片都如此繁瑣。為了更快獲取系統相冊照片和視頻,於是封裝了一個系統相冊的工具類ImagePicker,內部實現好代理和彈出/關閉的操作,方便自己平時調試。

Demo地址

  • 🌰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,本文就到此為止,祝大家新年快樂~

Demo地址