SwiftのAlamofireでpostするときはよくエラーが起きる。エラーを起こさないためには次の3点を意識する。
- サーバーのフレームワークがもっている独自csrfをオフにしているか
- サーバーはJSONを返しているか
- responseはJSONを受け付けるようにしているか
以下はもう少し細かいチェック項目である。
post先のurlが正しいか
url(おそらくはAPI)は完全に正しいか。最後にスラッシュがある場合は、Swift側のurlもそれに合わせる。
post先のurlが独自のcsrfをもっていないか?
Django(Pythonのフレームワーク)は独自のcsrf機能をもっているため、APIのviewにはcsrf_exemptをつける。例えばログインAPIは
@csrf_exempt
def api_login(request):
などとする。これはSwiftでなくweb側の問題である。
post先のurlが他のurlより優先順位が劣っていないか
Djangoなどではurlの切り替え(このurlには〇〇、あのurlには△△と振り分けること)をコードの上から順に行う。post先のurlが他のurlに優先順位で負けている場合、もちろんpostできない。これもSwift外の問題である。
responseJSON
postは次のようになる。
Alamofire.request(url, method: .post, parameters: parameters).responseJSON {response in
switch response.result {
case .success:
データのやりとりは基本的にJSONで行うため、responseはresponseJSONとする。
parameters
postで送るデータが辞書形式の場合、parametersは辞書形式でないといけない。
parametersのパラメーターとサーバー側が想定する変数の形式が異なる
parametersは文字列の辞書で送ることが多いと思う。サーバー側はその一部のパラメーターを使って、データベースに問い合わせているかもしれない。そのとき、あるパラメーターはテーブルのidと合わせていたら、そのパラメーターはもちろん整数型である必要がある。
json
case .success:内部ではJSONを取得する。
let json: JSON = JSON(response.result.value as Any)
あらかじめSwiftyJSONをインポートしていないといけない。
エラーの原因はだいたいサーバー側にある
postがうまくいかないとき、Swift側ではログを出力してエラーの所在をかなり絞りこんでいる。それでもこのページをたどり着いたということは、8割以上の可能性でサーバー側(Python、PHP、Ruby側)のurl、csrfに問題がある。
postはgetのように手軽にブラウザで確認できない(わけでないが、面倒)ので、問題の発見がどこにあるかわかりにくくなる。