Swift3.0でjsonパラメータをHTTP POST

potproject.net Advent Calendar 2016
8日目の記事です。

Swift3.0です。本当Swift2.x時代が強すぎて検索に全く引っかかってこないのが辛い。


もう結構前になってしまいますが、iOS10が公開され、iPhone7も発売されました。

しかし、相変わらず自分的にはiOS10もiPhone7も興味ありません。

でも、残念ながらiOS開発をしているとiOS10にも対応しなきゃならなくなり、

小規模なアプリを作っていたので、swift2.3からswift3.0に書き直すことに。

しかし、swift3.0はもう2.xの互換性をかなぐり捨てていて、公式でコンバータが用意されるくらいにめっちゃ変更されてます。

まあ大体はコンバートで対処できるのですが、http通信のコードの部分でエラーが出ていました。

調べるとやっぱりここはうまく自動変換ができない模様。

Swift 3 URLSession.shared() Ambiguous reference to member ‘dataTask(with:completionHandler:) error (bug)

で、大体の人が詰まっているようだったswift3.0でHTTPリクエストを送るコードを自分のメモがてら載せときます。

つかswiftは仕様変わりすぎなんだよね・・・

コピペエンジニアには辛すぎる言語だ。ググっても2と3が混合してて辛い。

まず、swift2.3のコード。バックアップ取ってなかったんで再現になりますが。
Swift2.xだとこんな感じです。
参考:http://qiita.com/sushichop/items/ac4ae99b905ce523c2fe

// create the url-request
        let urlString = "http://httpbin.org/post"
        var request = NSMutableURLRequest(URL: NSURL(string: urlString)!)

        // set the method(HTTP-POST)
        request.HTTPMethod = "POST"
        // set the header(s)
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")

        // set the request-body(JSON)
        var params: [String: AnyObject] = [
            "foo": "bar",
            "baz": [
                "a": 1,
                "b": 20,
                "c": 300
            ]
        ]
        request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: nil, error: nil)

        // use NSURLSessionDataTask
        var task = NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: {data, response, error in
            if (error == nil) {
                var result = NSString(data: data, encoding: NSUTF8StringEncoding)!
                println(result)
            } else {
                println(error)
            }
        })
        task.resume()

いろいろありますが、これはNSURLSessionDataTaskというものを使ってでHTTP POSTを送るようです。

多分今までのswiftだとこれが主流なのかな?

このNSURLSessionがswift3.0ではURLSessionになり、仕様も変わっています。

URLSession.DataTaskは、第一引数に NSMutableURLRequest型ではなくURLRequest型でないと動きません。

NSMutableURLRequestを受け渡すと、クラッシュします。

requestは明示的に型宣言してないため、コンバートが見逃したということですね。

しかもコンパイル時エラーも起きない。困りますね。

(他のブログだとこれでビルドが通らないらしい。もしかして修正されたのかも?

というか通り抜けてたならAppleさんが悪い・・・俺は悪くない

参考:https://blog.areare.net/archives/8321

URLRequestは、NSMutableURLRequestとほぼ同じように書けます。

というより、内部的にはほぼ同じものらしいので、なんでこれで通らなくなってしまったのかわからん。

let urlRequest = URLRequest(url: requestURL)

これを踏まえて、書きます。

        let urlString = "https://httpbin.org/post"
        var request = URLRequest(url: URL(string:urlString)!)

        // set the method(HTTP-POST)
        request.httpMethod = "POST"
        // set the header(s)
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")

        // set the request-body(JSON)
        let params: [String: Any] = [
            "foo": "bar",
            "baz": [
                "a": 1,
                "b": 20,
                "c": 300
            ]
        ]
        do{
            request.httpBody = try JSONSerialization.data(withJSONObject: params, options: [])
        }catch{
            print(error.localizedDescription)
        }
        // use NSURLSessionDataTask
        let task = URLSession.shared.dataTask(with: request, completionHandler: {data, response, error in
            if (error == nil) {
                let result = String(data: data!, encoding: .utf8)!
                print(result)
            } else {
                print(error)
            }
        })
        task.resume()

こんな感じかな。

初期に公開したコードはやっぱり間違っていました。ごめんなさい。

ちゃんとこのソースのままでjsonをpostできていることを確認しました。

後は、他にもいろいろ変わっているところがありました。

NSJSONSerialization.dataWithJSONObject([AnyObject], options: [options], error: [error])は、

JSONSerialization.data(withJSONObject: [Any], options: [options])に置き換わりました。

errorのコールバックがなくなった分、try-catchを行わないとコンパイルエラーとなります。

他にも、微妙に大文字から小文字へと変数名が変わったり。

iOS開発初心者のSwift3の道は険しい。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)