はじめに
初心者のハマりどころのひとつと思われるWebViewにまつわる話です(私もiOS初心者です)。
iOS10でWKWebViewを使用してPOSTでリクエストする時、httpBodyがnilになるというバグがあるようです。
バグについては、iOS10までとiOS11以降で検証されているこちらの記事が分かりやすいです。
解決策はこちらの記事を参考にしました。
前提条件
XCode 10.2.1
Swift4
DeploymentTarget: iOS10
解決案
今回は「はじめに」の参考にした記事で紹介されている、「URLSessionDataTaskで取得したデータをWKWebViewの以下のメソッドに渡す」方法で対応しました。
まずはURLSessionでリクエストを送信する処理を追加していきます。
今回はデータをjson形式にして送ります。
do-catch内でURLSessionDataTaskにリクエストの内容を渡して、リクエストを開始します。
@IBOutlet weak var webViewContainer: UIView!
private let url = "http://xxx.xxx.x.x"
override func viewDidLoad() {
super.viewDidLoad()
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config, delegate: self, delegateQueue: nil)
var request = URLRequest(url: URL(string: url)!)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
let params: [String: String] = [
"hoge": "hoge",
"huga": "huga"
]
do {
request.httpBody = try JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
let task = session.dataTask(with: request as URLRequest)
task.resume()
} catch {
print(error.localizedDescription)
}
}
URLSessionDataDelegateに、URLSessionで受け取ったデータをWebViewに渡す処理を実装します。UIを更新する処理なのでメインスレッドで行う必要があります。DispatchQueueを使ってメインスレッドでWebViewのロードを行います。
extension ViewController: URLSessionDataDelegate {
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
DispatchQueue.main.async(execute: {
let webView = WKWebView(frame: self.webViewContainer.bounds)
self.webViewContainer.addSubview(webView)
webView.load(data, mimeType: "text/html", characterEncodingName: "UTF-8", baseURL: URL(string: self.url)!)
})
}
}
Web側のソースです。
今回はローカルにXAMPPを入れてテストします。
<?php
$json = file_get_contents('php://input');
echo $json;
結果
まとめ
iOS13が発表されましたが、iOS10がサポートされている間は、この手法を使うことがあるかもしれません。ただ私はまだiOSの経験が浅いですし、この実装方法で正しいか分かりませんので、もっといい方法があれば知りたいです。
参考
iOS(swift)ガワアプリの作成で色々苦労した話
iOSのWKWebViewの3つのつまずきポイントと解決方法
SwiftでjsonをphpへPOSTする