json - 如何在 SwiftUI 中创建 json 'POST' 请求?
问题描述
我正在为一个学习编程的项目制作联系人列表应用程序,目前正在创建通过我创建的 Rest API 将联系人添加到数据库的方法。
下面的代码用于Add Contact
视图,我遵循了一些关于如何从表单中获取数据、将其转换为 JSON 并通过 POST 请求将其发送到数据库的教程。
这是我得到的代码,应该发生的是我应该看到打印responseJSON
,但这没有发生,实际上什么都没有发生,当我checkDetails
通过按下视图上的按钮运行函数时,我得到和 的打印body
,jsonData
但没有别的。甚至没有错误。
我在这里有点难过,因为我没有改变太多,如果有的话,从我遵循的教程,所以我猜这与我自己的代码有关。
任何帮助,将不胜感激!
import SwiftUI
import Combine
struct AddContact: View {
@State var id = 999
@State var first_name: String = ""
@State var last_name: String = ""
@State var phone_number: String = ""
@State var address: String = ""
@State var birthday = Date()
@State var birthdayString: String = ""
@State var create_date = Date()
@State var create_dateString: String = ""
@State var updated_date = Date()
@State var updated_dateString: String = ""
@State var manager = DataPost()
var body: some View {
if manager.formCompleted {
Text("Done").font(.headline)
}
VStack {
NavigationView {
Form {
Section() {
TextField("First Name", text: $first_name)
TextField("Last Name", text: $last_name)
}
Section() {
TextField("Phone Number", text: $phone_number)
TextField("Address", text: $address)
}
Section() {
DatePicker("Birthday", selection: $birthday, displayedComponents: .date)
}
Section() {
Button(action: {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .short
birthdayString = dateFormatter.string(from: birthday)
create_dateString = dateFormatter.string(from: create_date)
updated_dateString = dateFormatter.string(from: updated_date)
print("Clicked")
self.manager.checkDetails(id: self.id, first_name: self.first_name, last_name: self.last_name, phone_number: self.phone_number, address: self.address, birthday: self.birthdayString, create_date: self.create_dateString, updated_date: self.updated_dateString)
}, label: {
Text("Add Contact")
.fontWeight(.bold)
.multilineTextAlignment(.center)
})
}.disabled(first_name.isEmpty || last_name.isEmpty || phone_number.isEmpty || address.isEmpty)
}
}.navigationTitle("New Contact")
.navigationBarTitleDisplayMode(.inline)
}
}
}
class DataPost: ObservableObject {
var didChange = PassthroughSubject<DataPost, Never>()
var formCompleted = false {
didSet {
didChange.send(self)
}
}
func checkDetails(id: Int, first_name: String, last_name: String, phone_number: String, address: String, birthday: String, create_date: String, updated_date: String) {
let body: [String: Any] = ["data": ["id": id, "first_name": first_name, "last_name": last_name, "birthday": birthday, "phone_number": phone_number, "create_date": create_date, "updated_date": updated_date, "address": address]]
let jsonData = try? JSONSerialization.data(withJSONObject: body)
let url = URL(string: "https://flaskcontact-list-app.herokuapp.com/contacts")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("\(String(describing: jsonData?.count))", forHTTPHeaderField: "Content-Length")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = jsonData
print(body)
print(jsonData)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print(error?.localizedDescription ?? "No data")
return
}
let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
if let responseJSON = responseJSON as? [String: Any] {
print(responseJSON)
}
}
task.resume()
}
}
解决方案
好的,这是我使用的测试代码。虽然我使用的是 macos 12.beta、xcode 13.beta、目标 ios 15 和 macCatalyst。在 iPhone ios15 和 macos 12 上测试。在 xcode 12.5 和 macos 11.4 上“应该是一样的”。
import Foundation
import SwiftUI
import Combine
@main
struct TestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct AddContact: View {
@State var id = 999
@State var first_name: String = ""
@State var last_name: String = ""
@State var phone_number: String = ""
@State var address: String = ""
@State var birthday = Date()
@State var birthdayString: String = ""
@State var create_date = Date()
@State var create_dateString: String = ""
@State var updated_date = Date()
@State var updated_dateString: String = ""
@State var manager = DataPost()
var body: some View {
if manager.formCompleted {
Text("Done").font(.headline)
}
VStack {
NavigationView {
Form {
Section() {
TextField("First Name", text: $first_name)
TextField("Last Name", text: $last_name)
}
Section() {
TextField("Phone Number", text: $phone_number)
TextField("Address", text: $address)
}
Section() {
DatePicker("Birthday", selection: $birthday, displayedComponents: .date)
}
Section() {
Button(action: {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .short
birthdayString = dateFormatter.string(from: birthday)
create_dateString = dateFormatter.string(from: create_date)
updated_dateString = dateFormatter.string(from: updated_date)
print("Clicked")
self.manager.checkDetails(id: self.id, first_name: self.first_name, last_name: self.last_name, phone_number: self.phone_number, address: self.address, birthday: self.birthdayString, create_date: self.create_dateString, updated_date: self.updated_dateString)
}, label: {
Text("Add Contact")
.fontWeight(.bold)
.multilineTextAlignment(.center)
})
}.disabled(first_name.isEmpty || last_name.isEmpty || phone_number.isEmpty || address.isEmpty)
}
}.navigationTitle("New Contact")
.navigationBarTitleDisplayMode(.inline)
}
}
}
class DataPost: ObservableObject {
var didChange = PassthroughSubject<DataPost, Never>()
var formCompleted = false {
didSet {
didChange.send(self)
}
}
func checkDetails(id: Int, first_name: String, last_name: String, phone_number: String, address: String, birthday: String, create_date: String, updated_date: String) {
let body: [String: Any] = ["data": ["id": id, "first_name": first_name, "last_name": last_name, "birthday": birthday, "phone_number": phone_number, "create_date": create_date, "updated_date": updated_date, "address": address]]
let jsonData = try? JSONSerialization.data(withJSONObject: body)
// "https://flaskcontact-list-app.herokuapp.com/contacts"
let url = URL(string: "https://jsonplaceholder.typicode.com/posts")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("\(String(describing: jsonData?.count))", forHTTPHeaderField: "Content-Length")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = jsonData
let task = URLSession.shared.dataTask(with: request) { data, response, error in
print("-----> data: \(data)")
print("-----> error: \(error)")
guard let data = data, error == nil else {
print(error?.localizedDescription ?? "No data")
return
}
let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
print("-----1> responseJSON: \(responseJSON)")
if let responseJSON = responseJSON as? [String: Any] {
print("-----2> responseJSON: \(responseJSON)")
}
}
task.resume()
}
}
struct ContentView: View {
var body: some View {
AddContact()
}
}
推荐阅读
- remote-access - AnyDesk Entreprise - 自动地址簿分配
- c - strlen(null_terminated_array) 执行 printf("%zu", strlen(null_terminated_array)) 打印包含 '\0' 的 size_t
- angular - 为什么复选框不受变量控制?
- java - 列表中的 QueryDsl 元组
- html - HTML 注释上的 PhpStorm 警告
- php - PHP 7.4 与 Firebird Interbase
- amazon-web-services - 配置警报阈值的最佳实践
- xml - IRS A2A BulkRequestTransmitter 无效或过时的 XML 命名空间,但文件中的命名空间是正确的
- python - 在 Graph 执行中不允许迭代 `tf.Tensor`。使用 Eager 执行或使用 @tf.function 装饰此函数
- r - 当两列匹配时,Dplyr 使用自定义顺序在第三列中选择最大值