📡

通信処理をSwift Concurrencyで記載する

2022/01/08に公開

こちらの記事では無名関数をつかって通信処理を切り分けましたが
最近登場しました Swift Concurrency をつかって処理を考えてみます。
https://zenn.dev/yoneapp/articles/cb53b14d3790f8

前回はこのようなコードを作成しました。

override func viewDidLoad() {
    super.viewDidLoad()

    getUsers { [weak self] queryDocumentSnapshot in
        self?.showUsers(queryDocumentSnapshot: queryDocumentSnapshot)
    }
}

func getUsers(completion: @escaping ([QueryDocumentSnapshot]) -> Void) {
    let db = Firestore.firestore()

    db.collection("users").getDocuments { (querySnapshot, err) in
        if let err = err {
            print("Error getting documents: \(err)")
        } else {
             let userDocuments = querySnapshot!.documents
             completion(userDocuments)
        }
    }
}

func showUsers(queryDocumentSnapshot: [QueryDocumentSnapshot]) {
  // ここに userDocuments を使うコードが書いてある
}

この例では Firebase Firestore を利用しています。

Firestore もいずれ Swift Concurrency に正式対応するタイミングがあるかと思いますが
このように現時点では Closure で実装されたコードと Swift Concurrency を組み合わせるには
withCheckedThrowingContinuation を使用します。

次に、この実装を示します。

override func viewDidLoad() {
    super.viewDidLoad()

    Task {
        do {
            async let userDocuments = getUsers()
            showUsers(userDocuments: try await userDocuments)
        } catch {
            print(error)
        }
    }
}

func getUsers() async throws -> [QueryDocumentSnapshot] {
    try await withCheckedThrowingContinuation { continuation in
        let db = Firestore.firestore()

        db.collection("users").getDocuments { (querySnapshot, error) in
            if let error = error {
                continuation.resume(throwing: error)
            } else {
                 let userDocuments = querySnapshot!.documents
                continuation.resume(returning: userDocuments)
            }
        }
    }
}

func showUsers(userDocuments: [QueryDocumentSnapshot]) {
  // ここに userDocuments を使うコードが書いてある
}

参考資料

https://zenn.dev/akkyie/articles/swift-concurrency#既存のコードを-async%2Fawait-に対応させる

https://zenn.dev/youandtaichi/articles/ae9450c9de0030

https://zenn.dev/koher/articles/swift-concurrency-cheatsheet

Discussion