78211


## Swift 5.5 async await

ベータ版であるXcode 13をインストールして、`Swift 5.5 async await`を勉強して、`http
GET`を実装してみたのですが、これが最適解ですかね？

[code]

    import Foundation
    
    class API {
        func httpGet(for urlString: String) async throws -> Data? {
            guard let url = URL(string: urlString) else {
                return nil
            }
            
            var request = URLRequest(url: url)
            request.httpMethod = "GET"
    
            let (data, _) = try await URLSession.shared.data(for: request)
    
            return data
        }
    }
    
    class Sample {
        var data : String?
        
        func getData() {
            async {
                let api = API()
                guard let data = try await api.httpGet(for: "https://api.isevenapi.xyz/api/iseven/6/") else { return }
                if let dataString = String(data: data, encoding: .utf8) {
                    print(dataString)
                    self.data = dataString
                }
            }
        }
    }
    
    
    var sample = Sample()
    
    sample.getData()
    
[/code]


CC BY-SA 4.0
2021-07-15T12:45:42.133
78207
2021-07-15T14:49:20.687
40856
question
swift
Swift 5.5 async awaitを使ってのhttp GETはこれが最適解ですか？


まだ仕様も100%固まっていない新機能で、ベストプラクティスと言ったものも確立していないので、「これが最適解ですか」という質問に答えられる人は少ないと思います。以下もあくまで一個人の見解として。

* * *

  * 異常系以外では非nilの結果が得られるので、戻り値をOptionalにする必要はないのではないか
  * `getData()`で起動された処理の完了が通知されず、いつ`data`に正しい値が入るのかわからない

またXcode 13 betaの事情(と言うか、Apple/swift.org側の事情)ですが、`async {...}`はXcode 13 beta 3
では deprecated となっています。

私なら`getData()`も`async`にして、以下のような感じに書くでしょう。

[code]

    import Foundation
    
    class API {
        enum Errors: Error {
            case urlInvalid
        }
        
        func httpGet(for urlString: String) async throws -> Data {
            guard let url = URL(string: urlString) else {
                throw Errors.urlInvalid
            }
            
            var request = URLRequest(url: url)
            request.httpMethod = "GET"
    
            let (data, _) = try await URLSession.shared.data(for: request)
    
            return data
        }
    }
    
    class Sample {
        enum Errors: Error {
            case encodingInvalid
        }
        
        func getData() async throws -> String {
            let api = API()
            let data = try await api.httpGet(for: "https://api.isevenapi.xyz/api/iseven/6/")
            guard let dataString = String(data: data, encoding: .utf8) else {
                throw Errors.encodingInvalid
            }
            return dataString
        }
    }
    
    Task {
        do {
            let sample = Sample()
            let result = try await sample.getData()
            print(result)
        } catch {
            print(error)
        }
    }
    
[/code]


CC BY-SA 4.0
2021-07-15T14:49:20.687
78211
2021-07-15T14:49:20.687
13972
78207
answer