概要
SwiftでAPIと連携を実装します。
JSONレスポンスを取得して画面上に表示できるように設定します。
API連携
ContactFormViewに戻って送信ボタンをクリックしたときの動作を設定していきます。
Buttonにactionを追加していきます。
APIのURL、Method、Header、httpBodyの設定を行って、URLSessionを使ってデータ転送処理を行います。
転送でエラーが返ってきた場合の処理を記述します(コンソールにエラーを表示)。
また、レスポンスがステータスコード200以外もエラーなので、200以外が返ってきた場合の処理を記述しておきます(コンソールにエラーを表示)。
そうでなければ、APIのreturnがjsonで返ってくるのでそれをコンソールに表示させるようにします。
Button(action:{
+ let url = URL(string:"https://script.google.com/macros/s/{デプロイID}/exec")!
+
+ var request = URLRequest(url: url)
+
+ request.httpMethod="POST"
+ request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
+ request.httpBody="name=\(CFVM.name)&&email=\(CFVM.email)&&body=\(CFVM.contactBody)".data(using:.utf8)
+
+ let task = URLSession.shared.dataTask(with: request) { data, response, error in
+
+ if let error = error {
+ print("クライアントエラー: \(error.localizedDescription) \n")
+ return
+ }
+ guard let data = data, let response = response as? HTTPURLResponse else {
+ print("データがありませんでした。")
+ return
+ }
+
+
+ if response.statusCode == 200 {
+ do{
+ let result = try JSONSerialization.jsonObject(with: data) as! Dictionary<String,Any>
+ print(result["message"] as! String)
+ }catch{
+ print("ERROR")
+ }
+
+ }
+
+ }
+ task.resume()
}){
Text("送信")
.frame(minWidth: 160)
.foregroundColor(.white)
.padding(12)
.background(Color.accentColor)
.cornerRadius(8)
}
let url = URL(string:"https://script.google.com/macros/s/{デプロイID}/exec")!
var request = URLRequest(url: url)
request.httpMethod="POST"
request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.httpBody="name=\(CFVM.name)&&email=\(CFVM.email)&&body=\(CFVM.contactBody)".data(using:.utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("クライアントエラー: \(error.localizedDescription) \n")
return
}
guard let data = data, let response = response as? HTTPURLResponse else {
print("データがありませんでした。")
return
}
if response.statusCode == 200 {
do{
let result = try JSONSerialization.jsonObject(with: data) as! Dictionary<String,Any>
print(result["message"] as! String)
}catch{
print("ERROR")
}
}
}
task.resume()
確認
できたら、確認してみます。
実際の動作確認は、Viewを確認するだけではできないためエミュレータを立ち上げて実行します。
エミュレータを立ち上げて、Contactをクリックし、値を正しく(APIのバリデーションに引っかからないように)入力して送信ボタンをクリックすると「success!」が返ってきているのがわかります。
APIと連携はできるようになりました。
今、コンソールに表示しているメッセージを画面上部に表示させるようにしてみます。
初期値が空のmessageを用意し、messageが空でなかったらTextを表示するようにします。
struct ContactFormView: View {
@ObservedObject var CFVM = ContactFormViewModel()
+ @State var message = ""
var body: some View {
VStack{
Text("Contact").font(.title)
+ VStack{
+ if message != "" {
+ Text("\(message)")
+ .frame(maxWidth:.infinity)
+ .frame(height:50)
+ .background(.blue)
+ .foregroundColor(.white)
+ }
+ }
VStack{
Text("お問合わせフォーム").font(.headline).foregroundColor(.white)
}
.frame(maxWidth:.infinity)
.frame(height:100)
.background(.blue)
VStack{
if message != "" {
Text("\(message)")
.frame(maxWidth:.infinity)
.frame(height:50)
.background(.blue)
.foregroundColor(.white)
}
}
messageの値は、ボタンをクリックしたあとの「success!」をコンソールにprintしていた部分で設定します。
Button(action:{
let url = URL(string:"https://script.google.com/macros/s/{デプロイID}/exec")!
var request = URLRequest(url: url)
request.httpMethod="POST"
request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.httpBody="name=\(CFVM.name)&&email=\(CFVM.email)&&body=\(CFVM.contactBody)".data(using:.utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("クライアントエラー: \(error.localizedDescription) \n")
return
}
guard let data = data, let response = response as? HTTPURLResponse else {
print("データがありませんでした。")
return
}
if response.statusCode == 200 {
do{
let result = try JSONSerialization.jsonObject(with: data) as! Dictionary<String,Any>
- print(result["message"] as! String)
+ self.message = "\(result["message"] as! String)"
}catch{
print("ERROR")
}
}
}
task.resume()
保存して動作確認をしてみます。
送信ボタンをクリックすると上部にメッセージが表示されます。
最終的なコード
import SwiftUI
struct ContactFormView: View {
@ObservedObject var CFVM = ContactFormViewModel()
@State var message = ""
var body: some View {
VStack{
Text("Contact").font(.title)
VStack{
if message != "" {
Text("\(message)")
.frame(maxWidth:.infinity)
.frame(height:50)
.background(.blue)
.foregroundColor(.white)
}
}
VStack{
Text("お問合わせフォーム").font(.headline).foregroundColor(.white)
}
.frame(maxWidth:.infinity)
.frame(height:100)
.background(.blue)
VStack{
Text("お問合わせ内容を入力してください。").padding()
Group{
TextField("お名前",text:$CFVM.name)
.keyboardType(.default)
.textFieldStyle(RoundedBorderTextFieldStyle())
.frame(maxWidth: .infinity)
Text(CFVM.namePrompt)
.multilineTextAlignment(.leading)
.frame(maxWidth:.infinity,alignment: .leading)
.padding(.leading, 10.0)
.foregroundColor(.red)
.font(.caption2)
}.padding(.bottom, 10.0)
Group{
TextField("email",text:$CFVM.email)
.keyboardType(.emailAddress)
.autocapitalization(.none)
.textFieldStyle(RoundedBorderTextFieldStyle())
.frame(maxWidth: .infinity)
Text(CFVM.emailPrompt)
.multilineTextAlignment(.leading)
.frame(maxWidth:.infinity,alignment: .leading)
.padding(.leading, 10.0)
.foregroundColor(.red)
.font(.caption2)
}.padding(.bottom, 10.0)
Group{
TextField("問合わせ内容",text:$CFVM.contactBody)
.keyboardType(.emailAddress)
.textFieldStyle(RoundedBorderTextFieldStyle())
.frame(maxWidth: .infinity)
Text(CFVM.contactBodyPrompt)
.multilineTextAlignment(.leading)
.frame(maxWidth:.infinity,alignment: .leading)
.padding(.leading, 10.0)
.foregroundColor(.red)
.font(.caption2)
}.padding(.bottom, 10.0)
Button(action:{
let url = URL(string:"https://script.google.com/macros/s/AKfycbzZ_QO36OHfVPV1OgltU52jyBVyEdfHYHkdVBqB-xnUnU30E_rmhod18zjpVh-KJWoO/exec")!
var request = URLRequest(url: url)
request.httpMethod="POST"
request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.httpBody="name=\(CFVM.name)&&email=\(CFVM.email)&&body=\(CFVM.contactBody)".data(using:.utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("クライアントエラー: \(error.localizedDescription) \n")
return
}
guard let data = data, let response = response as? HTTPURLResponse else {
print("データがありませんでした。")
return
}
if response.statusCode == 200 {
do{
let result = try JSONSerialization.jsonObject(with: data) as! Dictionary<String,Any>
self.message = "\(result["message"] as! String)"
}catch{
print("ERROR")
}
}
}
task.resume()
}){
Text("送信")
.frame(minWidth: 160)
.foregroundColor(.white)
.padding(12)
.background(Color.accentColor)
.cornerRadius(8)
}
.opacity(CFVM.isComplete ? 1 : 0.5)
.disabled(!CFVM.isComplete)
Spacer()
}.frame(maxWidth:.infinity).frame(height:500)
}
}
}
struct ContactFormView_Previews: PreviewProvider {
static var previews: some View {
ContactFormView()
}
}