“エンジニアの困った”をメモるブログ

teckmemo

アプリ開発

Swift4で同期通信をする

更新日:

今回は、Swift4で同期HTTP通信を実現します。
APIを通して取得したデータを使って処理したい場合など、非同期でなくHTTP通信を待ってからしたい処理もあるかと思います。

スポンサーリンク

参考にしたSwift2のコード

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

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 ボタンで変換できないのが面倒ですね。。

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

完成したコード

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

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 {
    // 受け取ったデータに対する処理
}
Developerページはなかなか検索にも引っかからず忘れがちですが、活用していきたいですね!

-アプリ開発
-, ,

Copyright© teckmemo , 2019 All Rights Reserved.