Swift4で同期通信をする

今回は、Swift4で同期HTTP通信を実現します。
使いどきはあまりイメージできておりませんが、書き換えチャレンジです。

参考にしたSwift2のコード

まず、Swift4で同期HTTP通信をするためにこちらのサイトを参考にしました。
サイトに掲載されていたSwift2のコードも、勉強のため載せておきます。

https://53ningen.com/synchronous-http-request-swift/

public class HttpClientImpl {
    private let session: NSURLSession
    public init(config: NSURLSessionConfiguration? = nil) {
        self.session = config.map { NSURLSession(configuration: $0) } ?? NSURLSession.sharedSession()
    }
    public func execute(request: NSURLRequest) -> (NSData?, NSURLResponse?, NSError?) {
        var d: NSData? = nil
        var r: NSURLResponse? = nil
        var e: NSError? = nil
        let semaphore = dispatch_semaphore_create(0)
        session
            .dataTaskWithRequest(request) { (data, response, error) -> Void in
                d = data
                r = response
                e = error
                dispatch_semaphore_signal(semaphore)
            }
            .resume()
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
        return (d, r, e)
    }
}

Swift2からSwift4へ変換する

この状態で、Compiler Errorが6つ出ていました。
基本的には、Fixボタンをクリックしていったら良いんですが、、
dispatch_semaphore_waitだけ、Fixボタンでは消えてくれませんでした。😭

この問題については、AppleのDeveloperページを参考にします。
ときどき、こういったFixボタンで変換できないのが面倒ですね。。

https://developer.apple.com/documentation/dispatch/dispatchsemaphore

結果、次のようになりました。

完成したコード

全て変換し終えたコードがこちらです。

public class HttpClientImpl {
    private let session: URLSession
    public init(config: URLSessionConfiguration? = nil) {
        self.session = config.map { URLSession(configuration: $0) } ?? URLSession.shared
    }
    public func execute(request: URLRequest) -> (NSData?, URLResponse?, NSError?) {
        var d: NSData? = nil
        var r: URLResponse? = nil
        var e: NSError? = nil
        let semaphore = DispatchSemaphore(value: 0)
        session
            .dataTask(with: request) { (data, response, error) -> Void in
                d = data as NSData?
                r = response
                e = error as NSError?
                semaphore.signal()
            }
            .resume()
        _ = semaphore.wait(timeout: DispatchTime.distantFuture)
        return (d, r, e)
    }
}

また、使うときはこんな感じです。

// 通信先のURLを生成.
let myUrl:URL = URL(string: "https://www.example.com/xxx")!
let req = NSMutableURLRequest(url: myUrl)

let postText = "key1=value1&key2=value2"
let postData = postText.data(using: String.Encoding.utf8)

req.httpMethod = "POST"
req.httpBody = postData

let myHttpSession = HttpClientImpl()
let (data, _, _) = myHttpSession.execute(request: req as URLRequest)
if data != nil {
    // 受け取ったデータに対する処理
}