
potpro (ぽとぷろ)
Full-stuck engineer(Not Full-stack)
JS/PHP/Go/Docker/Nginxなど。技術または趣味寄りの発信ブログです。
全 86 記事Swift3.0でjsonパラメータをHTTP POST
potpro(ぼとぷろ)Swift3.0でjsonパラメータをHTTP POST
potproject.net Advent Calendar 20168日目の記事です。
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の道は険しい。
